我什么时候应该使用GC.SuppressFinalize()?

时间:2020-03-06 14:54:02  来源:igfitidea点击:

在.NET中,在什么情况下应该使用GC.SuppressFinalize()

使用此方法有什么优点?

解决方案

必须在实现IDisposable的对象的Dispose方法上调用该方法,这样,如果有人调用Dispose方法,GC将不会再次调用终结器。

请参阅:http://msdn.microsoft.com/en-us/library/system.gc.suppressfinalize.aspx

我们告诉系统已在终结器中完成的任何工作都已经完成,因此不需要调用终结器。从.NET文档:

Objects that implement the IDisposable
  interface can call this method from
  the IDisposable.Dispose method to
  prevent the garbage collector from
  calling Object.Finalize on an
  object that does not require it.

通常,大多数任何Dispose()方法都应该能够调用GC.SupressFinalize(),因为它应该清除将在终结器中清除的所有内容。

SupressFinalize只是提供一种优化,使系统不必费心将对象排队到终结器线程。正确编写的Dispose()/ finalizer可以在调用或者不调用GC.SupressFinalize()的情况下正常工作。

SuppressFinalize应该仅由具有终结器的类调用。通知垃圾收集器(GC)该对象已被完全清除。

拥有终结器的建议IDisposable模式为:

public class MyClass : IDisposable
{
    private bool disposed = false;

    protected virtual void Dispose(bool disposing)
    {
        if (!disposed)
        {
            if (disposing)
            {
                // called via myClass.Dispose(). 
                // OK to use any private object references
            }
            // Release unmanaged resources.
            // Set large fields to null.                
            disposed = true;
        }
    }

    public void Dispose() // Implement IDisposable
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    ~MyClass() // the finalizer
    {
        Dispose(false);
    }
}

通常,CLR在创建终结器时保留带有终结器的选项卡(使它们的创建成本更高)。 SuppressFinalize告诉GC该对象已正确清理,不需要进入终结器队列。它看起来像一个C ++析构函数,但功能却不一样。

SuppressFinalize优化并非微不足道,因为对象可以在终结器队列上等待很长时间。不要介意在其他对象上调用SuppressFinalize。那是一个严重的缺陷,等待发生。

设计准则通知我们,如果对象实现IDisposable,则不需要终结器,但是,如果我们有终结器,则应实现IDisposable以允许对类进行确定性清理。

大多数时候,我们应该可以摆脱IDisposable的清理资源。仅当对象保留非托管资源时,才需要终结器,并且需要确保这些资源被清除。

注意:有时,编码人员会添加一个终结器来调试其自己的IDisposable类的构建,以测试代码是否正确处理了其IDisposable对象。

public void Dispose() // Implement IDisposable
    {
        Dispose(true);
    #if DEBUG
        GC.SuppressFinalize(this);
    #endif
    }

    #if DEBUG
    ~MyClass() // the finalizer
    {
        Dispose(false);
    }
    #endif