Dispose、Finalize、SuppressFinalize 方法

Dispose, Finalize, SuppressFinalize methods

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

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() 方法?

是的,您可以实现这两种方法。

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

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
  }
}

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

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

忘记终结器。

在第一个模式中,GC.SuppresFinalize(this) 正在做的是告诉垃圾收集器它不应该在释放对象时调用终结器(~MyClass() 方法):如果您已经明确调用Dispose() 那么您 已经 调用了您的虚拟 Dispose(bool) 函数,那么为什么还要调用它呢?

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

如果一个对象被 GC 释放,它持有的所有托管引用也将被释放,因此在调用终结器时无需清除 托管 引用.

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

如果您忘记了 Dispose(),应该有最后一次释放它们的机会(当 GC 收集对象时,或者在应用程序运行时的最终清理时)。这就是为什么在正常模式下你还实现了一个终结器,并告诉它清理非托管资源如果你之前没有做过

请注意,与流行的看法相反,对 Dispose() 的调用没什么特别的,它只是一个方法调用:如果需要,您可以将其称为 FreeMyObject()FooBar() .它不会让垃圾收集器释放任何内存。使用 IDisposable 有一个 模式 ,如此重要以至于它获得了自己的语言语法结构(using 块),但仅此而已,一个模式。你可以做 Dispose() 做的同样的事情,而不用完全实现 IDisposable