将’IDisposable’嵌套在一个’using’语句中

关于在单个’using’语句中使用嵌套一次性用法的快速问题:我应该写出每个一次性使用语句,还是可以将它们嵌入一个? 例:

using( FileStream inFile = new FileStream( "myFile.txt", FileMode.Open ) ) using( GZipStream gzip = new GZipStream( inFile, CompressionMode.Decompress ) ) using( FileStream outFile = new FileStream( "myNewFile.txt", FileMode.CreateNew ) ) { gzip.CopyTo( outstream ); } 

 using( GZipStream gzip = new GZipStream( new FileStream( "myFile.txt", FileMode.Open ), CompressionMode.Decompress ) ) using( FileStream outFile = new FileStream( "myNewFile.txt", FileMode.CreateNew ) ) { gzip.CopyTo( outstream ); } 

好奇的是,当块完成执行时,来自“myFile.txt”的未命名的FileStream会被清除,因为它位于带有GZipStream的using语句中,或者它是否保持打开状态,并且需要在此之后的某个时间进行清理。

编辑:为了清楚,我不是在询问有关使用语句嵌套的问题。 我问的是,在另一个IDisposable的’using’语句中创建的IDisposable是否会在块的末尾被处理掉。 任何解释为什么或为什么不会被欣赏。

它取决于构造函数, GZipStream处理你在处理它时传入的流,除非你使用一个带有bool的重载并将true传递给leaveOpen

但是,这样做会冒风险。 如果GZipStream抛出ArgumentException因为流的CanRead属性为false则传入的流不会被处理掉。

就个人而言,我宁愿不依赖“不会出错”,而是通常采用防御性编码并使用3语句版本。


编辑:为了清楚,我不是在询问有关使用语句嵌套的问题。 我问的是,在另一个IDisposable的’using’语句中创建的IDisposable是否会在块的末尾被处理掉。 任何解释为什么或为什么不会被欣赏。

如果这是你的问题,那么答案是:不,只有被声明的对象( using var whatever = ... )将被处理,创建的任何其他对象都依赖于任何“外部”对象的代码。实现“链调用” Dispose()方法。

如果块执行完毕,来自“myFile.txt”的未命名的FileStream会被清除,因为它位于带GZipStream的using语句中

即使两个构造函数都成功,它仍然依赖于“拥有”类的设计。 StreamReader将关闭其BaseStream,但许多其他类不会。

您不希望您的代码依赖于如此模糊且易于更改的细节。

简单的答案是否定的 – 您需要包装每个对象。