9

我已经在 .NET 中编程了四年(主要是 C#),并且我广泛使用 IDiposable,但我还没有发现需要终结器。终结者有什么用?

4

5 回答 5

11

终结器是确保正确清理某些内容的最后尝试,通常保留给包装非托管资源的对象,例如不会被垃圾收集的非托管句柄等。

编写终结器确实很少见。幸运的是(与 不同IDisposable),终结器不需要传播;因此,如果您有一个ClassA带有终结器的 a 和一个ClassBwhich wraps ClassA,则ClassB不需要终结器 - 但很可能两者都ClassAClassB实现IDisposable.

对于托管代码,IDisposable通常就足够了。即使您没有正确清理,最终托管对象也会被收集(假设它们已被释放)。

于 2009-04-20T14:30:50.873 回答
4

终结器仅用于释放非托管资源,例如 GDI 位图句柄。如果您不分配任何非托管资源,那么您不需要终结器。一般来说,在终结器中触摸任何托管对象都是一个坏主意,因为不能保证终结的顺序。

另一种使用终结器的有用技术是在应用程序需要这样做时断言 Dispose 已被调用。这可以帮助捕获 DEBUG 构建中的编码错误:

void Dispose()
{
  GC.SuppressFinalize(this);
}
#if DEBUG
~MyClass()
{
  Debug.Fail("Dispose was not called.");
}
#endif
于 2009-04-20T14:36:45.290 回答
2

终结器是一种释放不受垃圾收集器控制的资源的机制,例如非托管句柄。虽然Dispose可能会这样做,但不能保证消费者会调用​​它。

于 2009-04-20T14:31:02.043 回答
1

终结器用于清理未处理的资源。

IE,没有任何东西强制你调用 Dispose(),但是垃圾收集器会自动调用终结器。

不应依赖此功能,因为无法保证垃圾收集何时(或是否)到达您的对象。

于 2009-04-20T14:30:38.050 回答
1

维基百科

...终结器是一段代码,可确保在获取的资源...不再使用时采取某些必要的操作[因为拥有的对象已被垃圾收集]

如果您在编写 IDisposables 时没有使用终结器,那么您很可能会发生内存泄漏,因为无法保证所有者实际上会调用 Dispose()。

MS 自己建议您将与此类似的内容写入您的实施者:

    public void Dispose()
    {
        this.Dispose(true);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (!this.isDisposed)
        {
            if (disposing)
            {
                GC.SuppressFinalize(this);
            }
        }
        //Dispose of resources here
        this.isDisposed = true;
    }

    ~DisposableSafe()
    {
        this.Dispose(false);
    }

    private bool isDisposed = false;

就个人而言,我无法忍受复制粘贴,所以我倾向于将其包装在一个抽象类中以供重用。

于 2009-04-20T14:37:33.477 回答