C# using语句是否只处理它创建的第一个变量?

C# using语句是否只处理它创建的第一个变量?,c#,idisposable,using,C#,Idisposable,Using,假设我有一个一次性对象MyDisposable,它将另一个一次性对象作为构造函数参数 using(MyDisposable myDisposable= new MyDisposable(new AnotherDisposable())) { //whatever } 假设myDisposable不在它的dispose方法中处理另一个disposable 这是否仅正确处置我的一次性产品?或者它也会处理另一个可丢弃的?它不会“处理”任何东西。它调用其中使用的对象的Dispose方法。你的

假设我有一个一次性对象
MyDisposable
,它将另一个一次性对象作为构造函数参数

using(MyDisposable myDisposable= new MyDisposable(new AnotherDisposable()))
{
     //whatever
}

假设
myDisposable
不在它的dispose方法中处理另一个disposable


这是否仅正确处置我的一次性产品?或者它也会处理另一个可丢弃的?

它不会“处理”任何东西。它调用其中使用的对象的
Dispose
方法。你的工作是清理其他东西。。可能通过调用另一个对象上的dispose来实现。

为什么不嵌套它们

using(var outer = new AnotherDisposable())
{
   using(var inner = new MyDisposable(outer))
   {
      //whatever
   }

}

现在至少你可以确定它们会被正确地处理掉。

使用
相当于

MyDisposable myDisposable = new MyDisposable(new AnotherDisposable());
try
{
    //whatever
}
finally
{
    if (myDisposable != null)
        myDisposable.Dispose();
}

因此,如果
myDisposable
没有调用另一个disposable,
using
也不会调用它。

在这种情况下,它不会处理另一个disposable。有两种解决方案

首先,您通常会执行以下操作:

using (AnotherDisposable anotherDisposable = new AnotherDisposable())
using (MyDisposable myDisposable= new MyDisposable(anotherDisposable))
{
}
然而,还有另一条路要走。当一个类获取一次性对象时,它自己会处理它所获取的对象,这是很正常的。例如,包装
流的
StreamReader
将处理它包装的
流。这意味着您选择的构造将起作用。您可以在
MyDisposable
中实现相同的功能,然后您所采用的方法就可以了。

C#的using语句提供了一个在对象上调用Dispose的语法快捷方式 使用try/finally块实现IDisposable。例如:

using (FileStream fs = new FileStream ("myFile.txt", FileMode.Open))
{
// ... Write to the file ...
}
编译器将其转换为: FileStream fs=newfilestream(“myFile.txt”,FileMode.Open)

finally块确保即使在出现异常时也调用Dispose方法 抛出,1或代码提前退出块

因此,使用单个块只能确保单个一次性对象得到处置。另一方面,您可以使用嵌套的using语句。像

using (myDisposable d = new myDisposable())
{
  using(Disposable2 d2 = new Disposable2())
  {
// do something and dispose...
  }
}
这将转换为

try
{
  // work around for myDisposable  

    try
     {
      // work around for Disposable2 
     }
    finally
    {
    if (d2 != null) 
         ((IDisposable)d2 ).Dispose();
    }    
}
finally
{
     if (d!= null)
          ((IDisposable)d).Dispose();
}

您仅使用
语句初始化了
中的一个一次性变量。
另一个可丢弃的
嵌套对象是通过正常初始化创建的,而不是通过
使用
。因此,只有您使用
using
语句创建的
myDisposable
变量才会被它自动处理。

是的,它会处理,它不会处理另一个disposable
,您需要手动管理
另一个一次性的
应该在
MyDisposable
实现上处理,因为它在那里使用。问题是使用double-using使FxCop显示CA2202:对象不应该多次处理,但这是因为在我使用的真实案例中,我知道innerDisposable由outerDisposable处理,所以我猜测这是否可以通过+1完成,这是处理清理的最佳方式。值得注意的是,甚至不需要第二组括号。这可以归结为您的格式设置偏好,但您可以使用语句直接堆叠在彼此的顶部,并使用相同的括号表示范围。这实际上是在回答我的问题时使用(MyDisposable MyDisposable=new MyDisposable(new AnotherDisposable()){…}
模式只有在
MyDisposable
的构造函数不仅承诺
MyDisposable.Dispose
将处理传递到构造函数中的对象,而且如果在构造函数本身期间发生任何异常,将立即处理传递的项时才是安全的,这是一种比它困难得多的模式应该是正确的。
try
{
  // work around for myDisposable  

    try
     {
      // work around for Disposable2 
     }
    finally
    {
    if (d2 != null) 
         ((IDisposable)d2 ).Dispose();
    }    
}
finally
{
     if (d!= null)
          ((IDisposable)d).Dispose();
}