什么是终结者?

时间:2009-04-20 14:27:44

标签: c# .net vb.net finalizer

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

5 个答案:

答案 0 :(得分:11)

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

确实很难写出终结者。幸运的是(与IDisposable不同),终结者不需要传播;所以如果你有一个ClassA有一个终结器,一个ClassB包裹ClassA,那么ClassB不需要终结器 - 但很可能都ClassAClassB将实施IDisposable

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

答案 1 :(得分:4)

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

使用终结器的另一个有用技术是声明在需要应用程序时已调用Dispose。这有助于捕获DEBUG构建中的编码错误:

void Dispose()
{
  GC.SuppressFinalize(this);
}
#if DEBUG
~MyClass()
{
  Debug.Fail("Dispose was not called.");
}
#endif

答案 2 :(得分:2)

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

答案 3 :(得分:1)

终结者用于清理资源,如果他们没有处置。

IE,没有什么可以强制你调用Dispose(),但是垃圾收集器会自动调用终结器。

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

答案 4 :(得分:1)

维基百科says

  

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

如果您在编写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;

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