Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

BinaryReader.Dispose(bool disposing) creates a local reference to stream. Why?

I found an unusual sample in FCL code.

This is method in System.IO.BinaryReader:

    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; 
    }

What impact on the execution logic has 'copyOfStream'?

like image 911
Illivion Avatar asked Nov 29 '12 21:11

Illivion


1 Answers

It's done so that m_stream will be set to null even if Stream.Close() throws an exception.

In response to comments

what kind of exception can be raised on Stream.Close()

When you close a stream, any buffered output is flushed, which can throw an exception, e.g. due to a network failure.

I'm not sure that this is a rationale. Usually we're calling Dispose in using block, and this means that variable will never used anyway

In the above, if Stream.Close() throws, then m_stream will already be null. With the following alternative, m_stream won't be set to null if Stream.Close() throws:

m_stream.Close(); // <== throws
m_stream = null;  // <== not executed if Close() throws

But in this case if we're talking about exception-safety, someone can retry call to Dispose method and will face NullReferenceException

It won't throw a NullReferenceException because it tests for null:

if (copyOfStream != null && !m_leaveOpen)
        copyOfStream.Close();
like image 65
Joe Avatar answered Sep 19 '22 05:09

Joe