为什么嵌套的using块会多次处理对象的dispose?

5

为什么嵌套的using块会多次处理一个对象?

参考 CA2202

在下面的示例中,创建在外部using语句中的Stream对象在内部using语句的结束处被释放,在包含流对象的StreamWriter对象的Dispose方法中释放。在外部using语句结束时,流对象再次被释放。第二次释放违反了CA2202。

using (Stream stream = new FileStream("file.txt", FileMode.OpenOrCreate))
{
    using (StreamWriter writer = new StreamWriter(stream))
    {
        // Use the writer object...
    }
}

我知道在大多数情况下我可以使用

using ()
using ()
{ }

当我无法做到时,我很高兴能够回归tryfinally,就像建议的那样,我只是想知道为什么它能这样工作。
这只是生成的代码可以被解释的最佳方式,"好的,使用块正在关闭,让我处理所有对象。"还是有一些原因让它以这种方式工作?
2个回答

11
using块本身不会多次释放任何东西。

在这种特定情况下,“问题”(实际上需要加引号,因为它只是在最抽象的数学意义上成为问题)在于StreamWriter占有底层流,因此当写入器由内部using释放时,它自动释放流。然后,外部using继续释放流。

这在实践中不是问题,因为Stream可以安全地多次释放。如果您必须做到完全正确,则仍然可以通过使用适当的 StreamWriter 构造函数使流仅被释放一次。


StreamWriter的哪个构造函数不会拥有流的所有权? - undefined

6

释放 StreamWriter 也会释放底层流。您可以配置 StreamWriter 不这样做。

主观注意:尽管如此,这个警告是错误的和无用的,因为多次处理对象通常是安全的(如果这些对象遵循常见的处理模式。所有 BCL 对象都可以被安全地多次处理)。


是的,对于IDisposable的实现指南的一部分要求是,它应该能够容忍多次调用。 - Adam Houldsworth
你如何配置 Streamwriter 以避免这种情况发生? - Chris
1
@Chris 那里有一个构造函数参数。如果不必要,我不建议使用它。在这里,它是不必要的。警告只是一些迂腐的垃圾。对于任何人完成他们的工作都没有帮助。 - usr
啊,好的。我也有疑问。我只是认为,如果你要提到可以配置它,那么也值得说一下如何配置。 - Chris

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接