Dispose,Finalize,SuppressFinalize方法

时间:2015-01-30 06:11:10

标签: c# garbage-collection

我可以在同一个类中实现这两个方法吗?

public class MyClass : IDisposable
{
  // some implementation
  // if i missed to call Dispose() method;
  ~MyClass()
  {
  // it means, clear all does not mananage resources 
  // but dont use Dispose() method 
  }
  public void Dispose()
  {
   // clear resources
   // if i call this method will i can do this:
   GC.SuppressFinalize()
   // it means dont use Finalizw method for this object
  }
}

我是对的吗?因为我无法理解这个GC.SuppressFinalize()方法?

1 个答案:

答案 0 :(得分:7)

是的,您可以按照自己的意愿实施这两种方法。

通常,如果对象可以同时具有托管和非托管引用,则正确的模式是:

public class MyClass : IDisposable
{
  ~MyClass()
  {
    Dispose(false);
  }
  public void Dispose()
  {
    GC.SuppressFinalize(this); 
    Dispose(true);
  }
  public virtual void Dispose(bool disposing)
  {
    if(disposing)
    {
      // clear MANAGED references
    }
    // free UNMANAGED resources
  }
}

但您可以根据需要实现此功能。这只是一种模式。例如,如果您没有任何非托管资源并且您的类已被密封(因此您可以确定它不会使用任何非托管资源),您可以像以下一样实现它:

public sealed class MyClass : IDisposable
{
  public void Dispose()
  {
    // release managed references
  }
}

忘记终结者。

在第一个模式中,GC.SuppresFinalize(this)正在做什么,告诉垃圾收集器在释放对象时不应该调用终结器(~MyClass()方法):如果你专门调用了{{ 1}}然后你已经已经调用了你的虚拟Dispose()函数,为什么要再次调用它?

问题是终结器本身在C#中是不确定的:你不知道什么时候会被调用...你甚至不能保证它甚至会被调用(尽管它会在正常清理期间,如果之前没有调用过),这就是Dispose(bool)存在的原因,它是确定性释放托管引用的方式,释放对象,并释放和释放由分配的非托管资源它

如果GC正在释放某个对象,那么它所拥有的所有托管引用也将被释放,因此在调用终结器时无需清除托管引用。

但是,您的应用程序应尽最大努力释放和释放它拥有的任何非托管资源。

如果您忘记了IDisposable,那么它们应该有最后一次机会被释放(当GC收集对象时,或者在应用程序运行时进行最后的清理)。在正常模式中你也可以实现终结器,并告诉它清理非托管资源如果你还没有完成它

请注意,与普遍看法相反,拨打Dispose()并不特别,只是方法调用:如果您愿意,可以将其称为Dispose()FreeMyObject()。它不会使垃圾收集器释放任何内存。使用FooBar()有一个模式,非常重要的是它获得了自己的语言语法结构(IDisposable块),但它只是一个模式。您可以执行与using相同的操作,而无需执行Dispose()