IDisposable GC.SuppressFinalize(this)位置

时间:2009-03-03 07:49:40

标签: c# .net idisposable suppressfinalize

我为我的代码使用默认的IDisposable实现模板(模式)。

片段:

public void Dispose()
{
    Dispose(true);

    GC.SuppressFinalize(this);
}

protected virtual void Dispose(bool isDisposing)
{
    if (!this.disposed)
    {
        if (isDisposing)
        {
            //cleanup managed resources
        }

        //cleanup unmanaged resources

        this.disposed = true;
    }
}

我的问题:为什么在Dispose公共方法中调用“GC.SuppressFinalize(this)”?在处置托管资源后,我会在受保护方法的“if(isDisposing)”部分放置“GC.SuppressFinalize(this)”。

像这样:

protected virtual void Dispose(bool isDisposing)
{
    if (!this.disposed)
    {
       if (isDisposing)
       {
           //cleanup managed resources

           GC.SuppressFinalize(this);
       }

       //cleanup unmanaged resources

       this.disposed = true;
    }
}

5 个答案:

答案 0 :(得分:11)

我认为它是模板设计模式的明显案例。

您的抽象类旨在处理所需的所有重要/必要任务(此处为GC.SuppressFinalize(this)),并允许派生类仅覆盖代码的某些部分。

这里有2个案例:
Snippet 1,SuppressFinalize,Dispose
Snippet 2,SuppressFinalize,Dispose(true)

这里,Snippet 1确保始终执行GC.SuppressFinalize。在代码片段2中,GC.SuppressFinalize的执行受派生类的支配。

因此,通过在Dispose方法中放置GC.SuppressFinalize,您作为类的设计者将始终确保无论派生类编写的代码是什么,都将执行GC.SuppressFinalize。

这只是在Dispose中编写SuppressFinalize而不是Dispose(true)的好处。

答案 1 :(得分:5)

Dispose(bool isDisposing)方法不属于IDisposable界面。

您通常会使用Dispose方法拨打Dispose(true),并从终结器调用Dispose(false),作为尚未处理对象的后备内容。

调用SuppressFinalize告诉GC,无需调用对象的终结器,大概是因为所有清理都是在调用Dispose时完成的。

如果你的班级没有终结者,那么你根本不需要拨打SuppressFinalize,因为没有终结者可以压制!

Joe Duffy有一些很棒的guidelines on disposal, finalization, garbage collection etc

答案 2 :(得分:1)

我认为任何一种布局都可以选择,但可能他们想在受保护的Dispose方法中强调“将所有释放代码放在此方法中”,因此他们将其他工件(抑制终结)放在别处。

另外,假设一个派生类有另一个原因来调用受保护的Dispose方法,但是仍然希望完成最终化(出于任何想象的原因,我不知道)。

答案 3 :(得分:1)

原因.Dispose是当托管代码(您的代码)处置对象从而选择退出完成时。人们通常会通过终结者创建另一条进入Dispose(bool处理)的路线,并且该调用对于终结者来说没有任何意义。

答案 4 :(得分:0)

这个想法是你的清理代码只应该被调用一次。但是有两个入口点:Dispose方法和对象终结器。调用Dispose时,您选择退出最终化,以便只调用一次清理代码。 code here可能会更好地说明它。

引用:

// NOTE: Leave out the finalizer altogether if this class doesn't 
// own unmanaged resources itself, but leave the other methods
// exactly as they are.