关于IDisposable的问题

时间:2010-10-28 11:43:22

标签: c# .net idisposable

我的问题是为什么我需要IDisposable?我有一个消耗一些资源的课程 需要被释放。我有两个选择

没有IDisposable

class SomeUtilityClass
{
 public Stop()
 {
   // free resources
 }
}

使用IDisposable

    class SomeUtilityClass, IDisposable
    {
     public void Dispose()
     {
       // free resources
     }
    }

那我为什么需要IDisposable呢?它没有如何命名该功能。

class Program
{

 public Main(..)
 {
   SomeUtilityClass _class = new SomeUtilityClass();

   // clean up when we've done

  _class.Stop();

   // OR
  _class.Dispose();

 }
}

7 个答案:

答案 0 :(得分:5)

因为C#支持IDisposable,您可以使用酷using语法:

using (IDisposable someDisposable = new ...)
{
    // your code with someDisposable 
}

这实际上是由编译器转换为:

IDisposable someDisposable = new ...
IDisposable someDisposable2 = someDisposable ;
try
{
    // your code with someDisposable 
}
finally
{
    if (someDisposable2 != null)
    {
        someDisposable2.Dispose();
    }
}

因此,如果在using块内发生任何异常,则无论如何都会处理您的对象。

答案 1 :(得分:3)

当您的类消耗非托管资源时,您应该只使用IDisposable,并且需要立即释放它们(流,数据库等)。

当有未处理的异常导致你的线程被卸载时,它还为CLR提供了一种“清理”的方法。

调用IDisposable会将对象标记为可立即用于垃圾收集,但如果未正确实现,则可能导致对象被提升为垃圾收集生成,这会导致内存压力(如果需要,请参阅通过c#3的Jeffery Richters CLR完整的解释)。

一个快速的谷歌转向了这个: http://kleahy-technical.blogspot.com/2009/01/idisposable-and-garbage-collection.html

我建议你阅读IDisposable模式,何时使用它,什么时候不要及其对GC和状态的影响。

编辑: stackoverflow上还有大量的信息: Use of Garbage Collection?

答案 2 :(得分:2)

在您的情况下,实施IDisposable没有太大意义,因为您可以手动处理您的资源。

IDisposable的一个常见用途是当您公开处理数据连接的接口时,您希望所有派生类在完成后进行处置。

考虑一下:

public interface IDataCtx
{
   void CallDB();
}

public class MyDataCtx : IDataCtx
{ 
   private SqlConnection dc;

   public MyDataCtx() { dc = new SqlConnection(); dc.Open(); }

   public void CallDB();
   {
       dc.Something();
   }
}

允许你做这样的事情:

IDataCtx ctx = new MyDataCtx();
ctx.CallDB();

但是等等,那个开放的连接怎么样?哦,哦!

如果你创建了IDataCtx : IDisposable(并在你的派生ctx中实现了代码),你可以这样做:

IDataCtx ctx;
using (ctx = new MyDataCtx())
{
   ctx.CallDB();
}

保证您使用的IDataCtx的任何实现,它将始终被处置(即使在例外的情况下)。

无论如何,这就是我如何使用它。 (加上它只是一种很好的做法)。

答案 3 :(得分:1)

IDisposableusing关键字进行互动,以便您自行清理,例如:

using (var file = new FileStream(...))
{
    file.Write(...);
}

在上面的代码中,FileStream在使用块完成后立即关闭,而不是等待垃圾收集。

答案 4 :(得分:1)

这是C#语言中使用的约定。

您还可以获得漂亮的using声明。

using (SomeUtilityClass _class = new SomeUtilityClass()) {

} // Dispose is automatically called

答案 5 :(得分:1)

除了能够使用using语句之外,它还为垃圾收集器提供了一个提示,可以从内存中删除该对象。

答案 6 :(得分:1)

如果您的类拥有非托管资源或您的类拥有托管的IDisposable资源,那么您应该实现IDisposable接口。

可以在此处找到关于何时实施IDisposable和Finalizer的简单易读的文章:http://nitoprograms.blogspot.com/2009/08/how-to-implement-idisposable-and.html