为什么有些人使用Finalize方法而不是Dispose方法?
在什么情况下你会使用Finalize方法而不是Dispose方法,反之亦然?
为什么有些人使用Finalize方法而不是Dispose方法?
在什么情况下你会使用Finalize方法而不是Dispose方法,反之亦然?
当前回答
finalizer方法在对象被垃圾收集时被调用,并且您无法保证何时会发生这种情况(您可以强制执行,但这会影响性能)。
另一方面,Dispose方法应该由创建类的代码调用,以便在代码处理完对象后立即清理和释放已获得的任何资源(非托管数据、数据库连接、文件句柄等)。
标准实践是实现IDisposable和Dispose,这样就可以在using语句中使用对象。例如使用(var foo = new MyObject()){}。在终结器中,你调用Dispose,以防调用代码忘记释放你。
其他回答
c#中Finalize和Dispose方法的区别。
GC调用finalize方法来回收非托管资源(如文件操作、windows api、网络连接、数据库连接),但GC调用它的时间不固定。它是由GC隐式调用的,这意味着我们对它没有低级控制。
处理方法:当我们从代码中调用它时,我们对它有低级别的控制。我们可以在觉得不可用的时候回收非托管资源。我们可以通过实现IDisposal模式来实现这一点。
以下是MCSD认证工具包(考试70-483)第193页中的一些关键信息:
析构函数≈(几乎等于)base.Finalize(),析构函数被转换为Finalize方法的重写版本,该方法执行析构函数的代码,然后调用基类的Finalize方法。这是完全不确定的,你不知道什么时候会被调用,因为这取决于GC。
如果一个类不包含托管资源和非托管资源,它就不应该实现IDisposable或具有析构函数。
如果类只有托管资源,它应该实现IDisposable,但不应该有析构函数。(当析构函数执行时,您仍然不能确定托管对象 所以你不能调用它们的Dispose()方法。)
如果类只有非托管资源,则需要实现IDisposable,并需要析构函数以防程序不调用Dispose()。
Dispose()方法必须能够安全地运行多次。您可以通过使用一个变量来跟踪它以前是否运行过来实现这一点。
Dispose()应该同时释放托管和非托管资源。
析构函数应该只释放非托管资源。当析构函数执行时,您 不能确定托管对象是否仍然存在,因此无论如何都不能调用它们的Dispose方法。这是通过使用规范的受保护的void Dispose(bool Dispose)模式获得的,其中只有在Dispose == true时才释放(Dispose)托管资源。
释放资源后,Dispose()应该调用GC。SuppressFinalize,这样对象就可以 跳过结束队列。
一个具有非托管资源和托管资源的类的实现示例:
using System;
class DisposableClass : IDisposable
{
// A name to keep track of the object.
public string Name = "";
// Free managed and unmanaged resources.
public void Dispose()
{
FreeResources(true);
// We don't need the destructor because
// our resources are already freed.
GC.SuppressFinalize(this);
}
// Destructor to clean up unmanaged resources
// but not managed resources.
~DisposableClass()
{
FreeResources(false);
}
// Keep track if whether resources are already freed.
private bool ResourcesAreFreed = false;
// Free resources.
private void FreeResources(bool freeManagedResources)
{
Console.WriteLine(Name + ": FreeResources");
if (!ResourcesAreFreed)
{
// Dispose of managed resources if appropriate.
if (freeManagedResources)
{
// Dispose of managed resources here.
Console.WriteLine(Name + ": Dispose of managed resources");
}
// Dispose of unmanaged resources here.
Console.WriteLine(Name + ": Dispose of unmanaged resources");
// Remember that we have disposed of resources.
ResourcesAreFreed = true;
}
}
}
这是我知道的最好的例子。
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
}
}
Finalize在该对象不再使用时由GC调用。
Dispose只是一个普通的方法,该类的用户可以调用它来释放任何资源。
如果用户忘记调用Dispose,如果类实现了Finalize,那么GC将确保它被调用。
finalizer方法在对象被垃圾收集时被调用,并且您无法保证何时会发生这种情况(您可以强制执行,但这会影响性能)。
另一方面,Dispose方法应该由创建类的代码调用,以便在代码处理完对象后立即清理和释放已获得的任何资源(非托管数据、数据库连接、文件句柄等)。
标准实践是实现IDisposable和Dispose,这样就可以在using语句中使用对象。例如使用(var foo = new MyObject()){}。在终结器中,你调用Dispose,以防调用代码忘记释放你。