为什么有些人使用Finalize方法而不是Dispose方法?
在什么情况下你会使用Finalize方法而不是Dispose方法,反之亦然?
为什么有些人使用Finalize方法而不是Dispose方法?
在什么情况下你会使用Finalize方法而不是Dispose方法,反之亦然?
当前回答
摘要如下-
You write a finalizer for your class if it has reference to unmanaged resources and you want to make sure that those unmanaged resources are released when an instance of that class is garbage collected automatically. Note that you can't call the Finalizer of an object explicitly - it's called automatically by the garbage collector as and when it deems necessary. On the other hand, you implement the IDisposable interface(and consequently define the Dispose() method as a result for your class) when your class has reference to unmanaged resources, but you don't want to wait for the garbage collector to kick in (which can be anytime - not in control of the programmer) and want to release those resources as soon as you are done. Thus, you can explicitly release unmanaged resources by calling an object's Dispose() method.
另外,另一个区别是——在Dispose()实现中,您也应该释放托管资源,而在Finalizer中不应该这样做。这是因为对象引用的托管资源很可能在准备完成之前就已经被清理了。
对于使用非托管资源的类,最佳实践是同时定义Dispose()方法和Finalizer,以便在开发人员忘记显式地释放对象时作为备用方案使用。两者都可以使用共享的方法来清理托管和非托管资源:-
class ClassWithDisposeAndFinalize : IDisposable
{
// Used to determine if Dispose() has already been called, so that the finalizer
// knows if it needs to clean up unmanaged resources.
private bool disposed = false;
public void Dispose()
{
// Call our shared helper method.
// Specifying "true" signifies that the object user triggered the cleanup.
CleanUp(true);
// Now suppress finalization to make sure that the Finalize method
// doesn't attempt to clean up unmanaged resources.
GC.SuppressFinalize(this);
}
private void CleanUp(bool disposing)
{
// Be sure we have not already been disposed!
if (!this.disposed)
{
// If disposing equals true i.e. if disposed explicitly, dispose all
// managed resources.
if (disposing)
{
// Dispose managed resources.
}
// Clean up unmanaged resources here.
}
disposed = true;
}
// the below is called the destructor or Finalizer
~ClassWithDisposeAndFinalize()
{
// Call our shared helper method.
// Specifying "false" signifies that the GC triggered the cleanup.
CleanUp(false);
}
其他回答
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.
finalizer方法在对象被垃圾收集时被调用,并且您无法保证何时会发生这种情况(您可以强制执行,但这会影响性能)。
另一方面,Dispose方法应该由创建类的代码调用,以便在代码处理完对象后立即清理和释放已获得的任何资源(非托管数据、数据库连接、文件句柄等)。
标准实践是实现IDisposable和Dispose,这样就可以在using语句中使用对象。例如使用(var foo = new MyObject()){}。在终结器中,你调用Dispose,以防调用代码忘记释放你。
这是我知道的最好的例子。
public abstract class DisposableType: IDisposable
{
bool disposed = false;
~DisposableType()
{
if (!disposed)
{
disposed = true;
Dispose(false);
}
}
public void Dispose()
{
if (!disposed)
{
disposed = true;
Dispose(true);
GC.SuppressFinalize(this);
}
}
public void Close()
{
Dispose();
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
// managed objects
}
// unmanaged objects and resources
}
}
完成
Finalizers should always be protected, not public or private so that the method cannot be called from the application's code directly and at the same time, it can make a call to the base.Finalize method Finalizers should release unmanaged resources only. The framework does not guarantee that a finalizer will execute at all on any given instance. Never allocate memory in finalizers or call virtual methods from finalizers. Avoid synchronization and raising unhandled exceptions in the finalizers. The execution order of finalizers is non-deterministic—in other words, you can't rely on another object still being available within your finalizer. Do not define finalizers on value types. Don't create empty destructors. In other words, you should never explicitly define a destructor unless your class needs to clean up unmanaged resources and if you do define one, it should do some work. If, later, you no longer need to clean up unmanaged resources in the destructor, remove it altogether.
拥有
Implement IDisposable on every type that has a finalizer Ensure that an object is made unusable after making a call to the Dispose method. In other words, avoid using an object after the Dispose method has been called on it. Call Dispose on all IDisposable types once you are done with them Allow Dispose to be called multiple times without raising errors. Suppress later calls to the finalizer from within the Dispose method using the GC.SuppressFinalize method Avoid creating disposable value types Avoid throwing exceptions from within Dispose methods
处理/确定模式
Microsoft recommends that you implement both Dispose and Finalize when working with unmanaged resources. The Finalize implementation would run and the resources would still be released when the object is garbage collected even if a developer neglected to call the Dispose method explicitly. Cleanup the unmanaged resources in the Finalize method as well as Dispose method. Additionally call the Dispose method for any .NET objects that you have as components inside that class(having unmanaged resources as their member) from the Dispose method.
其他人已经介绍了Dispose和Finalize之间的区别(顺便说一下,Finalize方法在语言规范中仍然被称为析构函数),所以我只补充一点Finalize方法派上用场的场景。
有些类型以一种易于在单个操作中使用和处理的方式封装一次性资源。一般用法通常是这样的:打开,读或写,关闭(Dispose)。它非常适合使用结构。
其他的稍微难一点。实例的WaitEventHandles不像这样使用,因为它们用于从一个线程发送信号到另一个线程。那么问题就变成了谁应该调用Dispose ?作为一种保护措施,这类类型实现了Finalize方法,该方法确保当应用程序不再引用实例时释放资源。