为什么有些人使用Finalize方法而不是Dispose方法?
在什么情况下你会使用Finalize方法而不是Dispose方法,反之亦然?
为什么有些人使用Finalize方法而不是Dispose方法?
在什么情况下你会使用Finalize方法而不是Dispose方法,反之亦然?
当前回答
Class instances often encapsulate control over resources that are not managed by the runtime, such as window handles (HWND), database connections, and so on. Therefore, you should provide both an explicit and an implicit way to free those resources. Provide implicit control by implementing the protected Finalize Method on an object (destructor syntax in C# and the Managed Extensions for C++). The garbage collector calls this method at some point after there are no longer any valid references to the object. In some cases, you might want to provide programmers using an object with the ability to explicitly release these external resources before the garbage collector frees the object. If an external resource is scarce or expensive, better performance can be achieved if the programmer explicitly releases resources when they are no longer being used. To provide explicit control, implement the Dispose method provided by the IDisposable Interface. The consumer of the object should call this method when it is done using the object. Dispose can be called even if other references to the object are alive.
注意,即使通过Dispose方法提供显式控制,也应该使用Finalize方法提供隐式清理。Finalize提供了一个备份,以防止程序员在调用Dispose失败时永久地泄漏资源。
其他回答
我今天一直在寻找这个问题的答案。我将在这里分享我的经验。我的答案是基于这个联系,因为它有我所见过的最清楚的解释。
当您的对象访问非托管资源时,您必须手动释放这些资源。这可以通过IDisposable或finalizer来完成,这意味着它们都会释放非托管资源。
经验法则: 实现IDisposable以释放非托管资源,调用方代码必须调用Dispose方法。如果调用者忘记调用Dispose()方法,您仍然可以提供一个方法来释放那些非托管资源。第一个选择是使用安全句柄来包装非托管资源。第二个选项是定义终结器。在这种情况下,建议使用安全手柄。
我认为这种联系是对这个问题最明确的答案。我不知道为什么人们在网上对这个问题给出复杂的解释。这让我很困惑,直到我找到了那个联系。
99%的情况下,你都不需要担心。但是,如果你的对象持有对非托管资源的引用(例如,窗口句柄,文件句柄),你需要为托管对象提供一种释放这些资源的方法。Finalize对释放资源进行隐式控制。它由垃圾回收器调用。Dispose是一种对资源释放进行显式控制的方法,可以直接调用。
关于垃圾收集的主题还有很多很多需要学习,但这只是一个开始。
其他人已经介绍了Dispose和Finalize之间的区别(顺便说一下,Finalize方法在语言规范中仍然被称为析构函数),所以我只补充一点Finalize方法派上用场的场景。
有些类型以一种易于在单个操作中使用和处理的方式封装一次性资源。一般用法通常是这样的:打开,读或写,关闭(Dispose)。它非常适合使用结构。
其他的稍微难一点。实例的WaitEventHandles不像这样使用,因为它们用于从一个线程发送信号到另一个线程。那么问题就变成了谁应该调用Dispose ?作为一种保护措施,这类类型实现了Finalize方法,该方法确保当应用程序不再引用实例时释放资源。
Finalize是backstop方法,由垃圾回收器在回收对象时调用。Dispose是“确定性清理”方法,应用程序调用它来释放有价值的本机资源(窗口句柄、数据库连接等),当它们不再需要时,而不是让它们无限期地保留,直到GC到达对象。
作为对象的用户,您总是使用Dispose。Finalize是针对GC的。
As the implementer of a class, if you hold managed resources that ought to be disposed, you implement Dispose. If you hold native resources, you implement both Dispose and Finalize, and both call a common method that releases the native resources. These idioms are typically combined through a private Dispose(bool disposing) method, which Dispose calls with true, and Finalize calls with false. This method always frees native resources, then checks the disposing parameter, and if it is true it disposes managed resources and calls GC.SuppressFinalize.
正如我们所知,dispose和finalize都用于释放非托管资源。 但不同的是finalize使用两个周期来释放资源,而dispose使用一个周期。