在C#中使用IDisposable与析构函数有什么区别?

时间:2008-12-03 23:04:22

标签: c# .net dispose destructor

我何时在类上实现IDispose而不是析构函数?我读过this article,但我仍然忽略了这一点。

我的假设是,如果我在一个对象上实现IDispose,我可以显式地“破坏”它,而不是等待垃圾收集器执行它。这是对的吗?

这是否意味着我应该总是在对象上显式调用Dispose?这有什么常见的例子?

7 个答案:

答案 0 :(得分:115)

终结器(也称为析构函数)是垃圾收集(GC)的一部分 - 当发生这种情况时(或者甚至发生这种情况)它是不确定的,因为GC主要是由于内存压力(即需要更多空间)而发生的。终结器通常仅用于清理非托管资源,因为托管资源将有自己的收集/处置。

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

以前有很多主题:

最后,请注意IDisposable对象也有一个终结器并不罕见;在这种情况下,Dispose()通常会调用GC.SuppressFinalize(this),这意味着GC不会运行终结器 - 它只会抛弃内存(便宜得多)。如果忘记Dispose()对象,终结器仍会运行。

答案 1 :(得分:23)

Finalize()方法的作用是确保.NET对象可以在收集垃圾时清理非托管资源 。但是,应尽快释放数据库连接或文件处理程序等对象,而不是依赖于垃圾回收。为此,您应该实现IDisposable接口,并使用Dispose()方法释放您的资源。

答案 2 :(得分:9)

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

  

此界面的主要用途是   释放非托管资源。   垃圾收集器自动生成   释放分配给a的内存   当该对象为no时,为托管对象   使用时间更长但是,没有   可以预测什么时候垃圾   将收集。此外,   垃圾收集器没有   非托管资源的知识   例如窗口句柄,或打开   文件和流。

     

使用Dispose方法   界面明确释放   非托管资源   与垃圾收集器。该   对象的使用者可以在对象为no时调用此方法   需要更长时间。

答案 3 :(得分:8)

C#析构函数中唯一应该出现的就是这一行:

Dispose(False);

就是这样。该方法不应该是其他任何东西。

答案 4 :(得分:4)

关于您是否应该经常致电Dispose的问题通常是激烈的辩论。请参阅this博客,了解.NET社区中受尊敬的个人的有趣观点。

就我个人而言,我认为Jeffrey Richter认为调用Dispose并非强制性的立场是非常弱的。他给出了两个证明他的观点的例子。

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

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

因此,除非有人有更引人注目的论点,否则我会留在“总是打电话给Dispose”阵营,并明白将会出现一些主要由于糟糕的设计选择而产生的边缘情况。

答案 5 :(得分:2)

真的很简单。我知道它已被回答,但我会再试一次,但会尽量保持简单。

通常不应使用析构函数。它只运行.net希望它运行。它只会在垃圾收集循环后运行。它可能永远不会在您的应用程序的生命周期中运行。因此,您不应该在析构函数中放置任何必须运行的代码。您也不能依赖类中的任何现有对象在运行时存在(它们可能已经被清理,因为无法保证析构函数的运行顺序)。

只要有一个创建需要清理的资源的对象(即文件和图形句柄),就应该使用

IDisposible。事实上,许多人认为,由于上面列出的原因,你在析构函数中放入的任何东西都应该被置于IDisisposable中。

大多数类会在终结器执行时调用dispose,但这只是一个安全防范,永远不应该依赖。当你完成它时,你应该明确地处理任何实现IDisposable的东西。如果你实现了IDisposable,你应该在终结器中调用dispose。有关示例,请参阅http://msdn.microsoft.com/en-us/library/system.idisposable.aspx

答案 6 :(得分:0)

这是另一篇很好的文章,它清除了IDisposable,GC和dispose周围的一些雾。

Chris Lyons WebLog Demystifying Dispose