我已经使用.NET编程四年了(主要是C#),我广泛地使用IDisposable,但我还没有找到需要使用终结器的情况。那么终结器有什么作用呢?
我已经使用.NET编程四年了(主要是C#),我广泛地使用IDisposable,但我还没有找到需要使用终结器的情况。那么终结器有什么作用呢?
Finalizer(终结器)是一种最后的手段,用于确保正确清理某些东西,通常用于封装非托管资源的对象,如非托管句柄等,这些资源不会被垃圾回收。
编写finalizer的情况确实很少。幸运的是(与IDisposable
不同),finalizer不需要传播;因此,如果您有一个带有finalizer的ClassA
和包装ClassA
的ClassB
,那么ClassB
不需要finalizer-但两个类都很可能实现IDisposable
。
对于托管代码,IDisposable
通常足够了。即使您没有正确清理,最终托管对象也会被收集(假设它们被释放了)。
Finalizers只用于释放像GDI位图句柄这样的非托管资源。如果您没有分配任何非托管资源,则不需要使用finalizer。通常,在finalizer中触及任何托管对象都是一个坏主意,因为finalization的顺序不能保证。
使用finalizer的另一种有用技术是在需要应用程序调用Dispose时断言已调用Dispose。这可以帮助在DEBUG版本中捕获编码错误:
void Dispose()
{
GC.SuppressFinalize(this);
}
#if DEBUG
~MyClass()
{
Debug.Fail("Dispose was not called.");
}
#endif
Finalizers(终结器)是一种释放不受垃圾回收控制的资源(例如未经管理的句柄)的机制。虽然Dispose
(释放)可能会这样做,但不能保证使用者会调用它。
维基百科说道:
……一个终结器是一段代码,确保在已获得的资源不再被使用(因为拥有对象已被垃圾回收)时采取某些必要的操作。
如果你在编写IDisposable时没有使用终结器,那么很可能会出现内存泄漏,因为不能保证所有者实际上会调用Dispose()。
微软自己建议您将类似于以下内容的代码编写到您的实现中:
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;
个人而言,我无法忍受复制粘贴,因此我倾向于将其封装在一个抽象类中以便重用。
最终器用于在资源未被处理时清理其资源。
也就是说,没有任何强制要求您调用Dispose()函数,但最终器会由垃圾回收自动调用。
不能依赖此功能,因为无法保证垃圾回收何时(或是否)到达您的对象。