GC,Finalize()和Dispose之间的关系是什么?

GC用于托管对象,Finalize用于非托管对象,这是我一直在阅读的内容。 Dispose是隐式的,Finalize是Explicit是我一直在阅读的内容。 有人可以给我一个模块的例子,其中所有三件事由于不同的原因被使用了吗?

GC是垃圾收集。 它是自动内存管理,用于处理托管堆上分配的对象的清理。 .NET GC采用标记和扫描算法。 当垃圾收集发生时,它基本上将要清理的堆部分中的所有对象都视为可恢复的。 然后它通过标记过程来扫描根。 即它识别应用程序仍在使用的对象。 完成后,剩余的对象有资格进行清理。 堆可以作为清理的一部分进行压缩。

Dispose和finalizer方法都提供了清理资源的选项,这些选项不由 GC处理。 例如,这可以是原生句柄等。 它们与回收托管堆上的内存无关。

必须在实现IDisposable的类型上显式调用Dispose。 它可以通过Dispose()方法本身或通过using构造来调用。 GC不会自动调用Dispose。

另一方面,终结器或析构函数(如语言规范所称)将在对象符合清除条件后的某个时间自动调用。 Finalize方法在专用线程上顺序执行。

Dispose()允许确定性地清理资源,而终结器可以在用户不调用Dispose()情况下充当安全网。

如果类型实现了终结器,则实例的清理会被延迟,因为必须在清理之前调用终结器。 即它需要额外的收集来回收该类型实例的内存。 如果类型也实现了IDisposable,则可以调用Dispose方法,然后实例可以从finalization中删除它自己。 这将允许清理对象,就好像它没有终结器一样。

如果你想深入研究这一点,我推荐通过C#by Jeffrey Richter的CLR 。 这是一本很棒的书,它涵盖了所有的血腥细节(我遗漏了一些细节)。 新的第3版刚刚发布。

.NET的一个好处是垃圾收集器。 在许多语言中,每一块内存都必须由开发人员管理 – 任何分配的内存最终都应该被释放。 在.NET(C#)中,垃圾收集器(GC)将负责为您释放内存的过程。 它跟踪对象的使用情况,在它们变为“无根”之后(即:应用程序中没有直接或间接引用该对象的引用),对象的内存会自动清除。

处理,或更具体地说, IDisposable和Dispose模式用于与GC分开处理资源。 出于各种原因,需要明确清理某些资源。 这包括使用“本机”API(其中.NET不知道已分配的内存),使用包装本机句柄的资源等。为了清楚地处理它,您实现了IDisposable和Dispose模式。

当对象即将被垃圾收集器收集时,将在对象上进行终结。 这提供了一个“安全网”,即如果比理想时间稍晚,仍然可以清理应该处理的物体。 通过实现终结器,您可以保证始终释放非托管资源。

大多数样本的问题是使用IDisposable有多种原因,并且正确的实现因您使用它的原因而异。 例如,如果直接包装本机资源,则应该实现终结器,但如果封装另一个IDisposable类型,则不需要终结器,即使您仍应实现IDisposable。 为了解决这个问题,我在博客上写了关于IDisposable和最终定稿的文章 ,描述了你使用IDisposable的多种原因,以及不同的原因。

您可能只想阅读我认为关于IDisposable,终结器和垃圾收集的权威文章,Shawn Farkas的CLR Inside Out:Digging into IDisposable 。

这篇文章对这个主题毫无疑问。