谁拥有.NET中的包裹流(例如TextWriter)?

use*_*740 9 .net c# stream object-lifetime objectdisposedexception

我最近遇到一个错误"ObjectDisposedException:无法访问已关闭的流"

[ObjectDisposedException: Cannot access a closed Stream.]
    System.IO.MemoryStream.Write(Byte[] buffer, Int32 offset, Int32 count) +10184402
    System.Security.Cryptography.CryptoStream.FlushFinalBlock() +114
    System.Security.Cryptography.CryptoStream.Dispose(Boolean disposing) +48
Run Code Online (Sandbox Code Playgroud)

使用以下格式的代码时:

using (var stream = new MemoryStream())
{
    using (var hashStream = new CryptoStream(stream,
                                    new SHA256Managed(), CryptoStreamMode.Write))
    using (var writer = new TextWriter(hashStream))
    {
        writer.Write("something");
    }
    // ^-- Exception occurs on hashStream Dispose
    //     While naively I assumed that TextWriter.Dispose wouldn't touch the
    //     underlying stream(s).
    return stream.ToArray();
}
Run Code Online (Sandbox Code Playgroud)

因此引发异常是因为TextWriter的Dispose释放了包装的Stream(hashStream).我的问题是这样的:

  1. 是否将此约定(使用默认构造函数/参数)应用于.NET中的所有流?

    是否有佳能讨论这种资源使用模式?例如,可以假设CryptoStream会关闭MemoryStream吗?我知道答案,并且还有其他问题,但如果有这样的话,我希望它在设计指南方面得到解决.

  2. 这种行为记录在哪里?

    我找不到TextWriter(stream)或者在CryptoStream构造函数中讨论的"所有权" - 当然我只是在查看错误的位置.(更新:显然我不能在读书,由itsme86此指出在TextWriter的构造文档中介绍.)

  3. 编写此类代码的普遍接受的方法是什么?

    也就是说,底层流需要被读取(在所有操作结束时,并且因此仍然打开),而所有的嵌套流应该被关闭/冲洗完全 -一个简单CryptoStream.Flush是不够的,例如.

its*_*e86 5

StreamWriter()文档中特别提到了这一点.

调用StreamWriter.Dispose时,StreamWriter对象在提供的Stream对象上调用Dispose().

  • 我可以算一下我在0手牌上利用这个功能的次数.真的希望他们没有引入这种流所有权的概念. (3认同)
  • .NET 4.x增加了指示Writer或Reader不处理流的功能. (2认同)

Yuv*_*kov 3

在阅读了C# 规范using声明并查看了一些已实现的流(内存、文件等)后,我发现默认行为是在调用. 在某些流中,您可以明确声明您不想处置底层流,例如:Dispose()DeflateStream

public DeflateStream(Stream stream, CompressionLevel compressionLevel, bool leaveOpen)
Run Code Online (Sandbox Code Playgroud)

leaveOpen 类型:System.Boolean true 表示在处置 DeflateStream 对象后使流对象保持打开状态;否则为假。

当然,您可以通过不使用 using 语句来解决处置问题,或者实现一个WrapperStream包装流但不处置底层流的类。