将’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,但许多其他类不会。
您不希望您的代码依赖于如此模糊且易于更改的细节。
简单的答案是否定的 – 您需要包装每个对象。