Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Object can be disposed of more than once - Best solution

Tags:

c#

dispose

I get the warning CA2202 (Object can be disposed more than once) on the following code:

using (Stream responseStream = response.GetResponseStream())
{
    if (responseStream != null)
        using (var br = new BinaryReader(responseStream))
        {
            responseValue = br.ReadBytes(500000);
        }
}

It seems like, the responseStreams Dispose is called when the BinaryReaders Dispose is called. Does the BinaryReader always call the Streams Dispose Method?

One solution would be to initialize the ResponseStream directly and let the BinaryReader take care about disposing the stream (which, of course, would only work, if the BinaryReader would dispose the stream in any situation)

Stream responseStream = response.GetResponseStream();
if(responseStream != null)
    using (var br = new BinaryReader(responseStream)) //Always disposes the response stream?
        [...]

I could use a try/finalize instead of the outer using statement to get something like this:

Stream responseStream = null;
try
{
    responseStream = response.GetResponseStream();
    if (responseStream != null)
        using (var br = new BinaryReader(responseStream))
        {
            responseValue = br.ReadBytes(500000);
        }
}
finally
{
    if(stream != null)
        stream.Dispose;
}

This isn't nice to look and unnecessary, when the BinaryReader always disposes the stream. Is there a better / preferred solution to solve this kind of problem?

like image 487
cb_dev Avatar asked Dec 17 '25 11:12

cb_dev


2 Answers

You can actually look how BinaryReader.Dispose is implemented:

protected virtual void Dispose(bool disposing) {
    if (disposing) {
        Stream copyOfStream = m_stream;
        m_stream = null;
        if (copyOfStream != null && !m_leaveOpen)
            copyOfStream.Close();
    }
    m_stream = null;
    m_buffer = null;
    m_decoder = null;
    m_charBytes = null;
    m_singleChar = null;
    m_charBuffer = null;
}

public void Dispose()
{
    Dispose(true);
}

Now, question is, what is m_leaveOpen? That's a flag which say if underlying stream should be disposed or not! It's by default set to false, which means underlying stream will be disposed:

public BinaryReader(Stream input) : this(input, new UTF8Encoding(), false) {
}

public BinaryReader(Stream input, Encoding encoding) : this(input, encoding, false) {
}

public BinaryReader(Stream input, Encoding encoding, bool leaveOpen) {
    // (...)
    m_leaveOpen = leaveOpen;
    // (...)
}

So you can skip using statement around you stream, as it will be disposed anyway:

responseStream = response.GetResponseStream();
if (responseStream != null)
{
    using (var br = new BinaryReader(responseStream))
    {
        responseValue = br.ReadBytes(500000);
    }
}

or just

using (var br = new BinaryReader(response.GetResponseStream()))
{
    responseValue = br.ReadBytes(500000);
}
like image 173
MarcinJuraszek Avatar answered Dec 19 '25 05:12

MarcinJuraszek


If you are using VS 2012 with .NET 4.5, you can create a BinaryReader that won't close the stream. E.g.:

using(var reader = new BinaryReader(theStream, new UTF8Encoding(), true)
{
//...
}

new UTF8Encoding is the default if you used the BinaryReader(Stream) constructor, if you don't want UTF8Encoding, you can use something else. The true signifies "yes, leave the stream open".

Constructs like :

public BinaryReader(
Stream   input,
Encoding encoding,
bool     leaveOpen
)

Hope this leads you to something you are looking for. Cheers.

like image 37
Gaurav Deochakke Avatar answered Dec 19 '25 06:12

Gaurav Deochakke



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!