3
votes

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?

2
Gaurav has the answer below, but I just wanted to point out that according to Microsoft's own documentation for IDisposable.Dispose() , "If an object's Dispose method is called more than once, the object must ignore all calls after the first one. - which means that this is supposed to be a non-issue (other than the fact that you might have disposed it in one place and then continue to attempt to use it later on, which is a different issue). - Matthew Watson

2 Answers

4
votes

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);
}
3
votes

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.