C# 对象可以多次处置-最佳解决方案

C# 对象可以多次处置-最佳解决方案,c#,dispose,C#,Dispose,我在以下代码中得到警告CA2202(对象可以被多次处置): using (Stream responseStream = response.GetResponseStream()) { if (responseStream != null) using (var br = new BinaryReader(responseStream)) { responseValue = br.ReadBytes(500000);

我在以下代码中得到警告CA2202(对象可以被多次处置):

using (Stream responseStream = response.GetResponseStream())
{
    if (responseStream != null)
        using (var br = new BinaryReader(responseStream))
        {
            responseValue = br.ReadBytes(500000);
        }
}
似乎在调用BinaryReaders Dispose时调用了responseStreams Dispose。BinaryReader是否总是调用Streams Dispose方法

一种解决方案是直接初始化ResponseStream,并让BinaryReader处理流(当然,只有在任何情况下BinaryReader处理流时,这才有效)

我可以使用try/finalize而不是outer using语句来获得如下内容:

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

当BinaryReader总是处理流时,这看起来不好,也没有必要。是否有更好的/首选的解决方案来解决此类问题

如果将VS 2012与.NET 4.5一起使用,则可以创建不会关闭流的BinaryReader。例如:

using(var reader = new BinaryReader(theStream, new UTF8Encoding(), true)
{
//...
}
如果使用BinaryReader(Stream)构造函数,则默认使用新的UTF8Encoding,如果不需要UTF8Encoding,则可以使用其他方法。true表示“是的,让溪流保持开放”

结构如下:

public BinaryReader(
Stream   input,
Encoding encoding,
bool     leaveOpen
)
希望这能引导你找到你想要的东西。 干杯。

您实际上可以看看它是如何实现的:

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);
}
现在,问题是什么是
m_leaveOpen
?这是一个标志,表示是否应该处理底层流!默认设置为
false
,这意味着将处理底层流:

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;
    // (...)
}
因此,您可以使用流周围的语句跳过
,因为它将被处理:

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

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

Gaurav给出了下面的答案,但我只是想指出,“如果一个对象的Dispose方法被多次调用,那么该对象必须忽略第一次调用之后的所有调用。-这意味着这应该不是问题(除了您可能在一个地方处置了它,然后以后继续尝试使用它,这是另一个问题)。我正在处理的项目基于.NET 4,因此leaveOpen选项不可用。但感谢您的提示!感谢您对.NET Framework参考源的详细解释和提示,我不知道:)
using (var br = new BinaryReader(response.GetResponseStream()))
{
    responseValue = br.ReadBytes(500000);
}