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

时间:2013-02-09 19:45:57

标签: 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
}

它的工作“很好”,实际上也是an answer 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.

这让我相信可能有另一种方法来处理这种情况,但我不知道它是什么。

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

4 个答案:

答案 0 :(得分:1)

如果您不需要MemoryStream的对象引用,这将正常工作

using (var bw = new BinaryWriter(new MemoryStream()))
{
    var memStream = bw.BaseStream as MemoryStream;
}

否则去多次使用。特别是在使用.NET框架对象的情况下,因为它们是使用正确的配置模式实现的。

当可能进行第二次置换调用的对象未正确实现置位模式时,双using语句可能会导致问题。

PS:你这样得到同样的警告:

using (var memStream = new MemoryStream())
{
    using (var bw = new BinaryWriter(memStream))
    {
        // work with ms and bw
    }
}

答案 1 :(得分:1)

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

using (var ms = new MemoryStream())
{
   using (var bw = new BinaryWriter(ms)) 
   {
    // work with ms and bw, both referenced here
   }
}

没有一种方法可以正确地将其缩小并避免警告。如果内部资源包装外部资源并且它们都在一起超出范围,则需要查阅文档:如果合同声明内部资源的dispose方法调用了包装对象的处置,则根本不需要将外部资源放在using块中。

话虽如此,大多数文档中可能都没有提及此类细节。您可以自己检查行为(通过继承和观察副作用),但是您必须小心,因为首先没有记录,这种行为可能会在将来的版本中发生变化。

所以如果你非常担心它,你可以保留双重使用块(以防万一),禁止警告并将整个块放在try{} catch (ObjectDisposedException e) {}中以完全保护自己的安全葫芦。

听起来偏执狂?取决于您正在使用的库: - )

答案 2 :(得分:1)

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

现在,对于大多数类来说,这不是一个真正的问题,因为它们应该(并且内存流)写入工作得很好,如果处理两次,只要你在处理之后不使用它(你'所以你可以安全地忽略警告。如果您希望警告消失,您可以将内存流从使用中取出,因为它已经被丢弃了。

答案 3 :(得分:-4)

我认为你不应该使用“using(...){}”:

using (var ms = new MemoryStream())

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