C# 同一使用块中的多个变量

C# 同一使用块中的多个变量,c#,dispose,idisposable,using,using-statement,C#,Dispose,Idisposable,Using,Using Statement,我目前正在使用两个对象,如下所示: using (var ms = new MemoryStream()) using (var bw = new BinaryWriter(ms)) { // work with ms and bw, both referenced here } 它工作“很好”,事实上也很好。但是,当我运行VS2012的代码分析工具时,会收到如下警告: CA2202 Do not dispose objects multiple times Object 'm

我目前正在使用两个对象,如下所示:

using (var ms = new MemoryStream())
using (var bw = new BinaryWriter(ms))
{
    // work with ms and bw, both referenced here
}
它工作“很好”,事实上也很好。但是,当我运行VS2012的代码分析工具时,会收到如下警告:

CA2202  Do not dispose objects multiple times   
Object 'ms' can be disposed more than once in method '<my method name>'. 
To avoid generating a System.ObjectDisposedException you should not 
call Dispose more than one time on an object.
CA2202不要多次处理对象
对象“ms”可以在方法“”中释放多次。
要避免生成System.ObjectDisposedException,不应
对对象多次调用Dispose。
这让我相信可能有另一种方法来处理这种情况,但我不知道它是什么


有人知道在一个
中以无警告的方式使用
块使用两个对象的“正确”方法是什么吗?

如果不需要
MemoryStream
的对象引用,这就可以了

using (var bw = new BinaryWriter(new MemoryStream()))
{
    var memStream = bw.BaseStream as MemoryStream;
}
否则,请使用多个选项。尤其是在使用.NET framework对象的情况下,因为它们是使用正确的dispose模式实现的

当可能有第二个dispose调用的对象没有正确实现dispose模式时,使用
语句的double
可能会导致问题

附言:这样你会得到同样的警告吗:

using (var memStream = new MemoryStream())
{
    using (var bw = new BinaryWriter(memStream))
    {
        // work with ms and bw
    }
}
我认为你不应该用“using(…){}”来表示:


因为操作系统管理内存并“处置”它

您认为这是一个单一的using块是不正确的。 示例中的代码是嵌套using块的语法糖,如下所示:

using (var ms = new MemoryStream())
{
   using (var bw = new BinaryWriter(ms)) 
   {
    // work with ms and bw, both referenced here
   }
}
没有一种方法可以正确地纠正此错误并避免警告。在内部资源包装外部资源并且它们一起超出范围的情况下,您需要查阅文档:如果契约声明内部资源的dispose方法调用了包装对象的dispose,您就不需要将外部资源放在using块中

尽管如此,在大多数文档中可能都不会提到这些细节。您可以自己检查该行为(通过继承和观察副作用),但必须小心,因为首先它没有记录在案,这种行为可能会在将来的版本中更改

因此,如果您对此非常担心,可以保留double-using块(以防万一),抑制警告并将整个块放入
try{}catch(ObjectDisposedException e){}
中,以完全保护您自己


听起来有点偏执?取决于您使用的库:-)

编写BinaryWriter类时,它将处理您在处理BinaryWriter时传递给它的底层流,除非您使用可选构造函数参数告诉它不要这样做。由于二进制写入程序正在处理底层内存流,并且您也在
using
块中处理它,因此它将被处理两次


现在,对于大多数类来说,这并不是一个真正的问题,因为它们应该(和内存流)被编写成只要两次释放就可以正常工作,只要在释放后不使用它(不使用),这样您就可以安全地忽略警告。如果你想让警告消失,你可以把内存流从使用中取出,因为它已经被处理了。

我喜欢这个想法,但是在中间的代码块中引用了内存流(<代码> TARARYAY()/代码>),你仍然可以通过<代码> BW.BaseTeRAM访问你的内存流。但是我会选择嵌套的
使用
处理内存流是一种很好的做法。这个答案很容易误导。Dispose方法可以由终结器自动调用,但(a)这与操作系统无关,它是垃圾收集机制的一部分,以及(b)您应该决定性地处置非托管资源。二进制写入的文档实际上指定它处置包装的资源,直到您使用表示不处置的构造函数重载为止。@Servy Good know:-)我个人会忽略此规则;这似乎被误导了。根据Dispose()的文档,“如果多次调用Dispose方法,对象就不能抛出异常。”我想可能会有一些实现不好的对象抛出异常,但总的来说,最好是处置所有可IDisposable的对象,并且不要担心某个对象被处置两次(这应该是不可操作的)@HansPassant:Thx,但我不一定称之为重复,因为它针对的是VB.net的语法(尽管事实上,你可以看到源自通用IL的相似之处),代码分析器并不关心你使用什么语言。
using (var ms = new MemoryStream())
{
   using (var bw = new BinaryWriter(ms)) 
   {
    // work with ms and bw, both referenced here
   }
}