11

我为我的代码使用默认的 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)”?在处置托管资源后,我会将“GC.SuppressFinalize(this)”放在受保护方法的“if (isDisposing)”部分中。

像这样:

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

           GC.SuppressFinalize(this);
       }

       //cleanup unmanaged resources

       this.disposed = true;
    }
}
4

5 回答 5

12

我想这是模板设计模式的一个明显案例。

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

这里有两种情况:
Snippet 1, SuppressFinalize, in Dispose
Snippet 2, SuppressFinalize, in Dispose(true)

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

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

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

于 2009-03-03T08:55:30.847 回答
6

Dispose(bool isDisposing)方法不是IDisposable接口的一部分。

您通常会Dispose(true)从您的Dispose方法调用,并Dispose(false)从您的终结器调用,作为尚未处置对象的情况下的后备。

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

如果您的班级没有终结器,那么您根本不需要调用SuppressFinalize,因为没有终结器可以抑制!

Joe Duffy在处理、完成、垃圾收集等方面有一些很好的指导方针

于 2009-03-03T10:56:05.363 回答
1

我认为可以选择任一布局,但可能他们想在受保护的 Dispose 方法中强调“将所有解除分配代码放入此方法中”,因此他们将另一个处理(抑制终结)工件放在其他地方。

此外,假设派生类有另一个调用受保护的 Dispose 方法的原因,但仍然希望发生终结(无论出于何种想象的原因,我不知道)。

于 2009-03-03T08:04:09.693 回答
1

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

于 2009-03-03T10:20:37.603 回答
0

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

引用:

// NOTE: Leave out the finalizer altogether if this class doesn't 
// own unmanaged resources itself, but leave the other methods
// exactly as they are. 
于 2009-03-03T07:54:50.073 回答