不使用 finalize 比较 dispose 真的更好吗?是否在第一次解析中删除非托管资源?
什么是抑制 finalize ?
您对 IDisposable 的实现应该是:
public MyClass : IDisposable
{
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected Dispose(bool disposing)
{
if( disposing )
{
// release unmanaged resource
}
// release managed resources
}
~MyClass()
{
Dispose(false);
}
}
如果一个对象有一个终结器,CLR 会在终结队列中保留对它的引用。如果您手动释放对象(调用 Dispose()),您已经删除了非托管资源(因为 dispose 的实现和终结器是共享的),因此无需调用终结器,您可以安全地从终结器中删除对象队列(调用 GC.SuppressFinalize(this))。
我写了一篇博客文章如何实现 IDisposable 和终结器:3 个简单规则,其中详细描述了何时以及如何使用每个规则。我也有一些关于这个主题的问答。
臭名昭著的关于如何实现的 Microsoft 文档IDisposable
(以及相应的 FxCop 规则)已经过时了。它们确实准确地描述了 Microsoft 如何IDisposable
在 .NET 1.0 中实现……。当 v2.0 发布时,BCL 中的几乎所有类都进行了改造,以遵循与我的博客文章中描述的指南类似的指南(唯一的区别是 Microsoft确实Dispose(bool)
为设计用作基类的类提供了保护)。特别是,据我所知,没有 BCL 类同时负责托管和非托管资源。
通常,Dispose 和 Finalize 都会清理所有非托管资源(例如句柄)。当 GC 检测到不再使用对象时,会发生以下两种情况之一。最好的情况是,如果对象不需要最终确定(它没有非托管资源或有人称为抑制终结),那么它会立即被清理。最坏的情况是,它被放到另一个区域来处理需要完成的事情,并且寿命更长(挂在那些非托管资源上的时间更长),直到最终终结器运行并且对象被完全清理。
拥有大量需要完成的对象会显着影响性能。Disposing 有两个目的:它返回非托管资源,并抑制终结器(假设您已正确实现 Dispose),这使 GC 中断。尽管如此,人们可能会忘记调用 Dispose(或使用 Using),因此终结器必须存在。尽量不要依赖它。