【问题标题】:What is the relationship between the using keyword and the IDisposable interface?using关键字和IDisposable接口有什么关系?
【发布时间】:2011-04-02 11:11:14
【问题描述】:

如果我使用using关键字,我还需要实现IDisposable吗?

【问题讨论】:

  • 也许你的意思是,“如果我使用'using'关键字,我还需要调用Dispose()吗?
  • @Chris Farmer...很好的编辑。我开始认为这是@Apple 的新垃圾压实机!!!
  • 正如其他人所指出的,using 语句的控制变量必须是实现IDisposable 的类型。然而,某些方法包含using 语句的事实并不意味着包含这些方法的类必须实现IDisposable。类实现IDisposable 的最常见原因是它们包含生命周期无法封装在using 语句中的资源。

标签: c# .net idisposable using-statement resource-management


【解决方案1】:

你不能没有另一个。

当你写的时候:

using(MyClass myObj = new MyClass())
{
    myObj.SomeMthod(...);
}

编译器会生成类似这样的东西:

MyClass myObj = null;
try
{
    myObj = new MyClass();
    myObj.SomeMthod(...);
}
finally
{
    if(myObj != null)
    {
        ((IDisposable)myObj).Dispose();
    }
} 

因此,您可以看到,在使用 using 关键字时,假定/要求实现 IDisposable。

【讨论】:

  • +1,但不假定 - 必需。如果类型未实现 IDisposable,则您在此处显示的编译器代码将出现无效强制转换异常。这就是为什么编译器通过给出编译时错误来防止这种情况发生,使得 IDisposable 需要,而不是假定,用于使用。
  • @Jimmy 是的,你是对的,假设我是这个意思。答案已更新。
【解决方案2】:

如果你使用using statement,封闭的类型必须已经实现IDisposable,否则编译器会报错。因此,将 IDisposable 实现视为使用的先决条件。

如果你想在你的自定义类上使用using 语句,那么你必须为它实现IDisposable。然而,这样做有点落后,因为为了它而这样做是没有意义的。只有当你有一些东西需要处理,比如非托管资源时,你才应该实现它。

// To implement it in C#:
class MyClass : IDisposable {

    // other members in you class 

    public void Dispose() {
        // in its simplest form, but see MSDN documentation linked above
    }
}

这使您能够:

using (MyClass mc = new MyClass()) {

    // do some stuff with the instance...
    mc.DoThis();  //all fake method calls for example
    mc.DoThat();

}  // Here the .Dispose method will be automatically called.

实际上这与写作相同:

MyClass mc = new MyClass();
try { 
    // do some stuff with the instance...
    mc.DoThis();  //all fake method calls for example
    mc.DoThat();
}
finally { // always runs
    mc.Dispose();  // Manual call. 
}

【讨论】:

  • @Troy:添加示例以突出显示说明。
  • 实际上,当您有“三明治”代码必须/应该在 finally 部分执行某些内容时,它是一种非常有用的模式。例如,一个常见的场景是一个忙碌的光标,步骤是... 1./复制现有的光标 2./将光标设置为您的等待光标 3./在最后部分复制回原始光标。使用 using 和 IDisposable,您可以编写类似 using(Busy.WaitCursor) { //WaitCursor 是一个静态属性,它返回 Busy 的实例,构造函数复制和设置,并且 dispose() 重新设置。 }
  • @Tim - 另一个很好的例子是更改控制台应用程序的颜色(我想我在 Wes Dyer 的博客上看到了这一点)。对于这样的任务,实现一个 Disposable 类有时很有用,该类简单地包装了一个在 Dispose() 上执行的 Action。但是,有时我不禁觉得它有点反模式。我想知道其他人对通用 Disposable 类的主题有何看法。
【解决方案3】:

你把事情弄糊涂了。您只能在实现 IDisposable 的东西上使用“using”关键字。

编辑:如果使用 using 关键字,则不必显式调用 Dispose,它将在 using 块的末尾自动调用。其他人已经发布了如何将 using 语句转换为 try - finally 语句的示例,并在 finally 块中调用 Dispose。

【讨论】:

  • 从记录集中读取数据时可以使用“using”关键字,对吗?
  • @Troy,是的,那是因为 IDataReader 实现了 IDisposable。
  • 只有当包装你的记录集的任何东西都实现了 IDisposable 时。如果它编译然后它实现 IDisposable....
【解决方案4】:

是的,using 关键字是这种模式的语法糖......(来自 msdn)

  Font font1 = new Font("Arial", 10.0f);
  try
  {
    byte charset = font1.GdiCharSet;
  }
  finally
  {
    if (font1 != null)
      ((IDisposable)font1).Dispose();
  }

编辑:一个有用的例子。

当您发现您在 finally 部分中始终如一地执行操作时,例如在将光标设置为等待光标后将其重置为默认值时,这是此模式的候选者...

  public class Busy : IDisposable
  {

    private Cursor _oldCursor;

    private Busy()
    {
      _oldCursor = Cursor.Current;
    }

    public static Busy WaitCursor
    {
      get
      {
        Cursor.Current = Cursors.WaitCursor;
        return new Busy();
      }
    }

    #region IDisposable Members

    public void Dispose()
    {
      Cursor.Current = _oldCursor;
    }

    #endregion
  }

叫...

using(Busy.WaitCursor)
{
  // some operation that needs a wait cursor.
}

【讨论】:

    【解决方案5】:

    Using 只会处理 disposable 对象。因此,在没有实现 IDisposable 相当无用的对象周围包装 using 块实际上会导致编译器错误。

    http://msdn.microsoft.com/en-us/library/yh598w02.aspx

    通常,当您使用 IDisposable 反对,你应该声明和 在 using 语句中实例化它。 using 语句调用 Dispose 正确的对象上的方法 方式,它也会导致对象 自己尽快超出范围 调用处置。使用范围内 块,该对象是只读的,并且 无法修改或重新分配。

    using 语句确保 即使出现异常也会调用 Dispose 在您调用方法时发生 物体上。你可以实现 通过放置对象获得相同的结果 在 try 块内,然后调用 在 finally 块中处理;实际上, 这就是 using 语句的方式 由编译器翻译。

    【讨论】:

      【解决方案6】:

      您必须实现 IDisposable 才能使用 using。如果您尝试在未实现 IDisposable 的类型上使用 using(),则会收到以下编译时错误:

      error CS1674: 'SomeType': type used in a using statement must be implicitly convertible to 'System.IDisposable'
      

      【讨论】:

        【解决方案7】:

        using 关键字已经实现,所以如果使用 using 关键字,则不必调用 IDisposable

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2023-04-04
          • 1970-01-01
          • 1970-01-01
          • 2020-11-09
          • 1970-01-01
          相关资源
          最近更新 更多