【发布时间】:2011-03-11 23:02:40
【问题描述】:
不使用 finalize 比较 dispose 真的更好吗?在第一次解析中 dispose 删除非托管资源吗?
什么是抑制 finalize ?
【问题讨论】:
标签: .net dispose finalize suppress
不使用 finalize 比较 dispose 真的更好吗?在第一次解析中 dispose 删除非托管资源吗?
什么是抑制 finalize ?
【问题讨论】:
标签: .net dispose finalize suppress
您的 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))。
【讨论】:
我写了一篇博文How to Implement IDisposable and Finalizers: 3 Easy Rules,详细描述了何时以及如何使用它们。我也有一些问答on the subject。
关于如何实现IDisposable(以及相应的 FxCop 规则)的臭名昭著的 Microsoft 文档已经过时了。他们确实准确地描述了 Microsoft 如何在 .NET 1.0 中实现 IDisposable...。当 v2.0 发布时,BCL 中的几乎所有类都进行了改造,以遵循与我的博客文章中描述的指南类似的指南(唯一的区别是 Microsoft 确实为类提供了受保护的 Dispose(bool)设计用作基类)。特别是,据我所知,没有 BCL 类同时负责托管和非托管资源。
【讨论】:
通常,Dispose 和 Finalize 都会清理任何非托管资源(例如句柄)。当 GC 检测到不再使用的对象时,会发生以下两种情况之一。最好的情况是,如果对象不需要最终确定(它没有非托管资源或有人称为抑制终结),那么它会立即被清理。最坏的情况是,它会被放到另一个区域来处理需要完成的事情,并且寿命更长(挂在那些非托管资源上的时间更长),直到最终终结器运行并且对象已被完全清理。
拥有大量需要完成的对象会显着影响性能。 Disposing 有两个目的:它返回非托管资源,并抑制终结器(假设您已正确实现 Dispose),这使 GC 休息。尽管如此,人们可能会忘记调用 Dispose(或使用 Using),因此终结器必须存在。尽量不要依赖它。
【讨论】: