【问题标题】:Does the using statement dispose only the first variable it create?using 语句是否只处理它创建的第一个变量?
【发布时间】:2013-06-26 10:10:11
【问题描述】:

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

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

假设 myDisposable 不要在其 dispose 方法中处理 AnotherDisposable

这只会正确处理myDisposable吗?或者它也处理AnotherDisposable

【问题讨论】:

  • 是的,会,不会处理AnotherDisposable,需要手动管理
  • AnotherDisposable 应该MyDisposable 实现上处理,因为它在那里使用。

标签: c# idisposable using


【解决方案1】:

using 相当于

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

因此,如果myDisposable 没有在AnotherDisposable 上调用 Dispose,using 也不会调用它。

【讨论】:

    【解决方案2】:

    为什么不嵌套它们?

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

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

    【讨论】:

    • 问题是使用双重使用使 FxCop 显示 CA2202: 对象不应该被多次处理,但这是因为在我使用的实际情况下,我知道 innerDisposable 是由outerDisposable 所以我猜这是否可以完成
    • +1,处理清理的最佳方式。请注意,甚至不需要第二组括号。这取决于您的格式偏好,但您可以将 using 语句直接堆叠在一起,并使用相同的括号来表示范围。
    【解决方案3】:

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

    【讨论】:

      【解决方案4】:

      在这种情况下,它不会处理AnotherDisposable。有两种解决方案。

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

      using (AnotherDisposable anotherDisposable = new AnotherDisposable())
      using (MyDisposable myDisposable= new MyDisposable(anotherDisposable))
      {
      }
      

      但是,还有一条不同的路要走。通常,当一个类使用一次性对象时,它自己会处理它使用的对象。例如。包装StreamStreamReader 将处理它包装的Stream。这意味着您选择的构造将起作用。您可以在MyDisposable 中实现相同的功能,然后您采用的方法就可以了。

      【讨论】:

      • 模式using (MyDisposable myDisposable = new MyDisposable(new AnotherDisposable()) {...} 模式只有在MyDisposable 的构造函数承诺不仅MyDisposable.Dispose 将处理传递给构造函数的对象,而且如果在执行过程中发生任何异常时,模式才是安全的。构造函数本身,传入的项目将立即被释放——这种模式比正确的模式要困难得多。
      【解决方案5】:

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

      using (FileStream fs = new FileStream ("myFile.txt", FileMode.Open))
      {
      // ... Write to the file ...
      }
      

      编译器将其转换为: FileStream fs = new FileStream("myFile.txt", FileMode.Open);

      try
      {
      // ... Write to the file ...
      }
      finally
      {
      if (fs != null) ((IDisposable)fs).Dispose();
      }
      

      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();
      }
      

      【讨论】:

        【解决方案6】:

        您只在using 语句中初始化了一个一次性变量。 AnotherDisposable 嵌套对象是通过正常初始化创建的,而不是由 using 创建的。所以只有你用using 语句创建的myDisposable 变量会被它自动释放。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-12-06
          • 1970-01-01
          • 2014-03-26
          • 2012-10-20
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多