What is the difference between using IDisposable vs a destructor in C#?

When would I implement IDispose on a class as opposed to a destructor? I read this article, but I'm still missing the point.

My assumption is that if I implement IDispose on an object, I can explicitly 'destruct' it as opposed to waiting for the garbage collector to do it. Is this correct?

Does that mean I should always explicitly call Dispose on an object? What are some common examples of this?

58596 次浏览

终结器(又名析构函数)是垃圾收集(GC)的一部分——这种情况何时(甚至是否发生)是不确定的,因为 GC 主要是由于内存压力(即需要更多的空间)而发生的。终结器通常只用于清理 无人管理资源,因为托管资源将有自己的收集/处理。

因此,IDisposable用于 决定性的清理对象,即现在。它不收集对象的内存(仍然属于 GC) ,但是用于关闭文件、数据库连接等。

以前有很多关于这方面的话题:

最后,请注意,IDisposable对象也有终结器并不罕见; 在这种情况下,Dispose()通常调用 GC.SuppressFinalize(this),这意味着 GC 不运行终结器——它只是丢弃内存(成本低得多)。如果忘记 Dispose()对象,则终结器仍将运行。

The role of the Finalize() method is to ensure that a .NET object can clean up unmanaged resources when garbage collected. However, objects such as database connections or file handlers should be released as soon as possible, instead on relying on garbage collection. For that you should implement IDisposable interface, and release your resources in the Dispose() method.

MSDN上有一个非常好的描述:

The primary use of this interface is 到 释放非托管资源。 The garbage collector automatically 释放分配给 当托管对象为 no 时 使用时间更长。但是,它是 < strong > not 可以预测何时发生垃圾 收集将发生 , 垃圾收集器 < strong > 没有 非管理资源的知识 such as window handles, or open 文件 和流

使用此 接口到 明确释放 共同管理的非管理资源 和垃圾收集者在一起 当对象为 no 时,对象 的使用者可以调用此方法 longer needed.

其实很简单。我知道它已经被回答,但我会再次尝试,但会尽量保持它尽可能简单。

一般不应使用析构函数。它只是运行。Net 想让它运行。它只会在垃圾收集器循环之后运行。它可能永远不会在应用程序的生命周期中实际运行。出于这个原因,您不应该在析构函数中放入任何“必须”运行的代码。您也不能依赖类中的任何现有对象在运行时存在(它们可能已经被清除,因为不保证析构函数的运行顺序)。

只要有一个对象创建了需要清理的资源(即文件和图形句柄) ,就应该使用 IDisposile。事实上,许多人认为,由于上面列出的原因,您放入析构函数中的任何东西都应该放入 IDisposable。

在执行终结器时,大多数类都会调用释放,但这只是作为一种安全保护措施,不应该依赖它。完成后,应该显式释放任何实现 IDisposable 的内容。如果确实实现了 IDisposable,则应在终结器中调用释放。有关示例,请参见 http://msdn.microsoft.com/en-us/library/system.idisposable.aspx

C # 析构函数中唯一应该包含的内容是这一行:

Dispose(False);

就是这样,这个方法里不应该有其他东西。

下面是另一篇很好的文章,它清除了一些围绕着 IDisposable、 GC 和 Dispose 的薄雾。

克里斯 · 莱昂斯网络日志揭秘处置

你关于是否应该总是调用 Dispose的问题通常是一个激烈的争论。请参阅 this博客,了解来自受人尊敬的个人的有趣观点。NET 社区。

就个人而言,我认为杰弗里 · 里希特认为打电话给 Dispose不是强制性的立场是极其软弱的。他举了两个例子来证明他的观点。

在第一个示例中,他说在 Windows 窗体控件上调用 Dispose在主流场景中是乏味和不必要的。但是,他没有提到,在这些主流场景中,Dispose实际上是由控件容器自动调用的。

在第二个示例中,他指出,开发人员可能错误地认为应该主动地处理来自 IAsyncResult.WaitHandle的实例,而没有意识到该属性懒惰地初始化等待句柄会导致不必要的性能损失。但是,这个例子的问题是,IAsyncResult本身并没有遵循微软自己发布的处理 IDisposable对象的指导方针。也就是说,如果一个类持有对 IDisposable类型的引用,那么该类本身应该实现 IDisposable。如果 IAsyncResult遵循这一规则,那么它自己的 Dispose方法就可以决定哪些组成成员需要处置。

因此,除非有人有更有说服力的论点,否则我将继续坚持“总是调用 Dispose”阵营,因为我知道将会出现一些边缘案例,这些案例主要是由于糟糕的设计选择而产生的。