C# GC、Finalize() 和 Dispose 之间的关系是什么?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2344240/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-07 01:38:20  来源:igfitidea点击:

what is relation between GC, Finalize() and Dispose?

c#.net

提问by Lost

GC is for managed objects and Finalize is for unmanaged objects thats what I have been reading. Dispose is implicit and Finalize is Explicit is what I have been reading. Can somebody give me one example of one module in which all three thing have been used for different reasons?

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

采纳答案by Brian Rasmussen

GC is garbage collection. It is the automatic memory management, that handles cleanup of objects allocated on the managed heap. The .NET GC employs a mark and sweep algorithm. When a garbage collection occurs it basically considers all object in the part of the heap to be cleaned as recoverable. Then it goes through a marking process where it scans for roots. I.e. it identifies objects that are still in use by the application. Having done that the remaining objects are eligible for cleanup. The heap may be compacted as part of the cleanup.

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

Dispose and finalizer methods both offer an option for cleaning resources, that are nothandled by GC. E.g. this could be native handles and the like. They have nothing to do with reclaiming memory on the managed heap.

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

Dispose must be called explicitly on a type which implement IDisposable. It can be called either through the Dispose()method itself or via the usingconstruct. The GC will not call Dispose automatically.

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

A finalizer or destructor (as the language specification calls it) on the other hand will automatically be called sometimeafter the object was eligible for cleanup. Finalize methods are executed sequentially on a dedicated thread.

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

Dispose()allows deterministic cleanup of resources while a finalizer can act as a safety net in case the user doesn't call Dispose().

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

If a type implements a finalizer, cleanup of instances is delayed as the finalizer must be called prior to cleanup. I.e. it will require an additional collect to reclaim the memory for instances of the type. If the type implements IDisposable as well, the Dispose method can be called and then the instance can remove itself from finalization. This will allow the object to be cleaned up as if it didn't have a finalizer.

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

If you want to dig into this, I recommend CLR via C# by Jeffrey Richter. It is a great book and it covers all the gory details of this (I left out a number of details). The new 3rd edition was just released.

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

回答by Mark Seemann

You may just want to read what I consider the definitive article on IDisposable, finalizers and garbage collection, Shawn Farkas' CLR Inside Out: Digging into IDisposable.

您可能只想阅读我认为关于 IDisposable、终结器和垃圾收集的权威文章 Shawn Farkas 的CLR Inside Out:深入研究 IDisposable

This article leaves very little doubt about the subject.

这篇文章对这个主题几乎没有任何疑问。

回答by Reed Copsey

One of the benefits of .NET is the garbage collector. In many languages, every piece of memory must be managed by the developer- any allocated memory should eventually be released. In .NET (C#), the Garbage Collector (GC) will take care of the process of releasing memory for you. It tracks the usage of your objects, and after they become "unrooted" (ie: there are no references within your application to that object, directly or indirectly), the object's memory is automatically cleaned up.

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

Dispose, or more particularly, IDisposableand the Dispose pattern, is used to handle resources separately from the GC. Some resources need to be cleaned up explicitly, for various reasons. This includes using a "native" API (where .NET doesn't know about the allocated memory), using a resource that wraps native handles, etc. In order to handle this cleanly, you implement IDisposableand the Dispose pattern.

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

Finalization occurs on objects when they are about to be collected by the garbage collector. This provides a "safety-net" where by an object that should have been disposed can still be cleaned up, if a bit later than ideal. By implementing a finalizer, you can guarantee unmanaged resources are always released.

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

The problem with most samples is that there are multiple reasons to use IDisposable, and the proper implementation differs depending on the reason you are using it. For example, if you wrap a native resource directly, you should implement a finalizer, but if you encapsulate another IDisposable type, a finalizer is not necessary, even though you should still implement IDisposable. In order to address this, I've written about IDisposable and finalization in depth on my blog, describing the multiple reasons you would use IDisposable, and different patterns for different reasons.

大多数示例的问题是使用 IDisposable 有多种原因,正确的实现因您使用它的原因而异。例如,如果你直接包装一个原生资源,你应该实现一个终结器,但如果你封装另一个 IDisposable 类型,则终结器是不必要的,即使你仍然应该实现 IDisposable。为了解决这个问题,我在我的博客 中深入写了IDisposable 和 finalization,描述了使用 IDisposable 的多种原因,以及出于不同原因的不同模式。