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

dgenwo3n  于 2023-06-25  发布在  .NET
关注(0)|答案(7)|浏览(133)

我什么时候会在类上实现IDispose,而不是析构函数?我读了this article,但我仍然没有抓住重点。
我的假设是,如果我在一个对象上实现IDispose,我可以显式地“析构”它,而不是等待垃圾收集器来执行它。是这样吗?
这是否意味着我应该总是显式地对对象调用Dispose?有哪些常见的例子?

wb1gzix0

wb1gzix01#

终结器(又名析构函数)是垃圾收集(GC)的一部分--它是不确定的,因为GC主要是由于内存压力(即,垃圾收集)造成的。需要更多的空间)。终结器通常只用于清理 * 非托管 * 资源,因为托管资源将有自己的收集/处置。
因此,IDisposable用于 * 确定性地 * 清理对象,即它不收集对象的内存(仍然属于GC)-但用于例如关闭文件、数据库连接等。
以前有很多关于这方面的主题:

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

mspsb9vt

mspsb9vt2#

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

5gfr0r5j

5gfr0r5j3#

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

Dispose(False);

就这样。那个方法里不应该有别的东西。

hl0ma9xz

hl0ma9xz4#

MSDN上有一个很好的描述:
此接口的主要用途是释放非托管资源。垃圾回收器会在托管对象不再使用时自动释放分配给该对象的内存。但是,无法预测垃圾回收何时发生。此外,垃圾收集器不了解非托管资源,如窗口句柄,或打开的文件和流。
使用此接口的Dispose方法可以与垃圾回收器一起显式释放非托管资源。对象的消费者可以在不再需要该对象时调用此方法。

ia2d9nvy

ia2d9nvy5#

关于是否应该总是调用Dispose的问题通常会引起激烈的争论。请参阅this博客,了解.NET社区中受人尊敬的个人的有趣观点。
就我个人而言,我认为Jeffrey Richter关于调用Dispose不是强制性的立场是非常薄弱的。他举了两个例子来证明他的观点。
在第一个例子中,他说在Windows窗体控件上调用Dispose是乏味的,在主流场景中是不必要的。然而,他没有提到在那些主流场景中,Dispose实际上是由控件容器自动调用的。
在第二个例子中,他指出开发人员可能错误地认为IAsyncResult.WaitHandle中的示例应该被积极地丢弃,而没有意识到该属性延迟初始化等待句柄,从而导致不必要的性能损失。但是,这个例子的问题是,IAsyncResult本身并不遵守微软自己发布的处理IDisposable对象的指导方针。也就是说,如果一个类持有对IDisposable类型的引用,那么该类本身应该实现IDisposable。如果IAsyncResult遵循这个规则,那么它自己的Dispose方法就可以决定它的哪些组成成员需要处理。
因此,除非有人有更令人信服的论点,否则我将留在“总是调用Dispose”阵营,因为我知道会有一些边缘案例,主要是由于糟糕的设计选择而产生的。

iqih9akk

iqih9akk6#

其实很简单。我知道它已经被回答了,但我会再试一次,但我会尽量保持它的简单。
析构函数通常不应该使用。它只是run.net希望它运行。它只会在垃圾回收周期后运行。它可能永远不会在应用程序的生命周期中实际运行。出于这个原因,你不应该把任何代码放在一个“必须”运行的析构函数中。你也不能依赖于类中的任何现有对象在运行时存在(它们可能已经被清理了,因为析构函数的运行顺序不确定)。
只要有一个对象创建了需要清理的资源(即文件和图形句柄),就应该使用IDisposible。事实上,许多人认为,由于上面列出的原因,你放在析构函数中的任何东西都应该被放置在IDisposable中。
大多数类都会在终结器执行时调用dispose,但这只是作为一个安全保护,永远不应该依赖。当您完成了IDisposable的操作时,您应该显式地释放它。如果您确实实现了IDisposable,则应该在finalizer中调用dispose。参见http://msdn.microsoft.com/en-us/library/system.idisposable.aspx以获得示例。

ax6ht2ek

ax6ht2ek7#

这里是另一个精美的文章,它清除了一些围绕IDisposable,GC和处置的薄雾。
Chris Lyons WebLog Demystifying Dispose

相关问题