【问题标题】:Object can be disposed of more than once - Best solution对象可以多次处理 - 最佳解决方案
【发布时间】:2014-07-11 03:05:27
【问题描述】:

我在以下代码中收到警告 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 会在任何情况下处理流时才会起作用)

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

我可以使用 try/finalize 而不是外部 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 总是处理流时,这看起来不太好而且没有必要。是否有更好/首选的解决方案来解决此类问题?

【问题讨论】:

  • Gaurav 有下面的答案,但我只想指出according to Microsoft's own documentation for IDisposable.Dispose()"如果一个对象的 Dispose 方法被多次调用,该对象必须忽略第一次之后的所有调用一个。 - 这意味着这应该是一个非问题(除了你可能已经将它放在一个地方然后继续尝试使用它的事实,这是一个不同的问题) .

标签: c# dispose


【解决方案1】:

您实际上可以查看BinaryReader.Dispose 是如何实现的:

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;
    // (...)
}

因此,您可以跳过流周围的 using 语句,因为它无论如何都会被处理:

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

【讨论】:

  • 感谢.NET Framework参考源的详细解释和提示,我不知道:)
【解决方案2】:

如果您在 .NET 4.5 中使用 VS 2012,您可以创建一个不会关闭流的 BinaryReader。例如:

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

如果您使用 BinaryReader(Stream) 构造函数,则默认使用新的 UTF8Encoding,如果您不想要 UTF8Encoding,则可以使用其他内容。 true 表示“是的,让流保持打开状态”。

类似的构造:

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

希望这会引导您找到您正在寻找的东西。 干杯。

【讨论】:

  • 我正在处理的项目基于 .NET 4,因此 leaveOpen 选项不可用。但是感谢您的提示!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-12
  • 1970-01-01
  • 2020-08-11
  • 1970-01-01
  • 1970-01-01
  • 2023-03-13
相关资源
最近更新 更多