BinaryReader.Dispose(bool disposing)创建一个流的本地引用。为什么?

5
我在FCL代码中发现了一个不寻常的样本。
这是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; 
    }

“copyOfStream”对执行逻辑有什么影响?
1个回答

9

这样做是为了即使Stream.Close()抛出异常,m_stream也将被设置为null。

回应评论

Stream.Close()会引发什么样的异常?

当关闭流时,任何缓冲的输出都会被刷新,这可能会引发异常,例如由于网络故障。

我不确定这是否是一种合理的做法。通常我们在using块中调用Dispose,这意味着变量永远不会被使用

在上述代码中,如果Stream.Close()抛出异常,则m_stream已经为null。而使用以下替代方案,如果Stream.Close()抛出异常,则m_stream不会被设置为null:

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

但如果我们在谈论异常安全性的话,有人可能会尝试重新调用Dispose方法,却面临着NullReferenceException。

这不会抛出NullReferenceException是因为代码进行了空值检测:

if (copyOfStream != null && !m_leaveOpen)
        copyOfStream.Close();

谢谢!我也假设了那个选项,但是Stream.Close()会引发什么样的异常呢?我没有找到任何信息。 - Illivion
我不确定这是否是合理的。通常我们在using块中调用Dispose,这意味着变量将永远不会被使用。但是在这种情况下,如果我们谈论异常安全性,有人可以重试调用Dispose方法,并面临NullReferenceException。 - Sergey Teplyakov
也许另一个线程在我们进行空值检查和调用实例方法“Close()”之间可以将“m_stream”设置为“null”? - Jeppe Stig Nielsen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接