为什么有些人使用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失败时永久地泄漏资源。
其他回答
99%的情况下,你都不需要担心。但是,如果你的对象持有对非托管资源的引用(例如,窗口句柄,文件句柄),你需要为托管对象提供一种释放这些资源的方法。Finalize对释放资源进行隐式控制。它由垃圾回收器调用。Dispose是一种对资源释放进行显式控制的方法,可以直接调用。
关于垃圾收集的主题还有很多很多需要学习,但这只是一个开始。
finalizer方法在对象被垃圾收集时被调用,并且您无法保证何时会发生这种情况(您可以强制执行,但这会影响性能)。
另一方面,Dispose方法应该由创建类的代码调用,以便在代码处理完对象后立即清理和释放已获得的任何资源(非托管数据、数据库连接、文件句柄等)。
标准实践是实现IDisposable和Dispose,这样就可以在using语句中使用对象。例如使用(var foo = new MyObject()){}。在终结器中,你调用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);
}
这是我知道的最好的例子。
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
}
}
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失败时永久地泄漏资源。