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

我最近遇到一个错误“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 

使用以下格式的代码时:

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

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

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

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

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

    我找不到TextWriter(stream)CryptoStream构造函数中讨论的“所有权” – 当然我只是在查看错误的位置。 (更新:显然我在阅读时失败了,正如它的me86所指出的那样,这在TextWriter构造函数文档中有记录。)

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

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

在阅读using语句C#spec并查看一些实现的流(内存,文件等)之后,我看到默认行为是在调用Dispose()时处理底层流。 在某些流中,您可以明确声明您不想处理底层流,就像在DeflateStream

 public DeflateStream(Stream stream, CompressionLevel compressionLevel, bool leaveOpen) 

leaveOpen类型:System.Boolean如果在处理DeflateStream对象后保持流对象处于打开状态,则为true;否则为false。 否则,是的。

当然,您可以通过不使用using语句或者实现包装流而不处理基础流的WrapperStream类来处理处理。

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

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