Sam*_*uel 131
当您的对象被垃圾收集时调用终结器方法,并且您无法保证何时会发生这种情况(您可以强制它,但这会损害性能).
Dispose另一方面,该方法旨在由创建您的类的代码调用,以便您可以在代码完成时清理和释放您已获取的任何资源(非托管数据,数据库连接,文件句柄等).你的对象.
标准做法是实施IDisposable,Dispose以便您可以在using陈述中使用您的对象.如using(var foo = new MyObject()) { }.在你的终结者中,你打电话Dispose,以防呼叫代码忘记丢弃你.
Bri*_*sen 115
其他人已经介绍了Dispose和之间的区别Finalize(顺便说一下,这个Finalize方法在语言规范中仍然被称为析构函数),所以我只想添加一些关于Finalize方法派上用场的方案.
某些类型以易于使用的方式封装一次性资源,并在一次操作中处理它们.一般用法通常是这样的:打开,读取或写入,关闭(Dispose).它非常适合using构造.
其他人则有点困难.WaitEventHandles因为它们用于从一个线程发送到另一个线程,所以实例不会像这样使用.那么问题就变成谁应该呼吁Dispose这些?作为这样的安全措施类型实现了一种Finalize方法,该方法确保在应用程序不再引用实例时处理资源.
ito*_*son 64
Finalize是一个backstop方法,当它回收一个对象时由垃圾收集器调用.Dispose是"确定性清理"方法,由应用程序调用以在不再需要时释放有价值的本机资源(窗口句柄,数据库连接等),而不是将它们无限期地保留,直到GC转向对象.
作为对象的用户,您始终使用Dispose.最终确定是GC.
作为类的实现者,如果您拥有应该处理的托管资源,则实现Dispose.如果您拥有本机资源,则实现Dispose和Finalize,并且都调用释放本机资源的公共方法.这些习语通常通过私有Dispose(bool disposing)方法组合,Dispose调用为true,Finalize调用为false.此方法始终释放本机资源,然后检查disposing参数,如果为true,则会释放托管资源并调用GC.SuppressFinalize.
Gen*_*Ziy 42
最终确定
protected,不是public或者private不能直接从应用程序的代码中调用该base.Finalize方法,同时,它可以调用该方法部署
IDisposable对每一个都有一个终结类型Dispose方法后,确保对象不可用.换句话说,避免Dispose在调用方法后使用对象.Dispose所有IDisposable类型Dispose多次调用而不会引发错误.Dispose使用该GC.SuppressFinalize方法抑制稍后从方法中调用终结器Dispose方法中抛出异常处理/最终模式
Dispose,并Finalize与非托管资源工作时.Finalize即使开发人员忽略了Dispose明确调用该方法,实现也会在对象被垃圾回收时仍然会释放资源.Finalize方法和Dispose方法中的非托管资源.另外,从Dispose方法中为该类中的任何.NET对象(具有非托管资源作为其成员)调用该Dispose方法.Bhu*_*ale 31
当此对象不再使用时,GC会调用Finalize.
Dispose只是一个普通的方法,这个类的用户可以调用它来释放任何资源.
如果用户忘记调用Dispose,并且该类已实现Finalize,则GC将确保调用它.
Mir*_*mvs 17
MCSD认证工具包(考试70-483)第193页中有一些关键词:
析构函数≈(它几乎等于)base.Finalize(),析构函数被转换为Finalize方法的覆盖版本,该方法执行析构函数的代码,然后调用基类的Finalize方法.然后它完全不确定,你无法知道什么时候会被调用因为取决于GC.
如果类不包含托管资源且没有非托管资源,则不需要实现IDisposableor具有析构函数.
如果类只有托管资源,它应该实现IDisposable,但它不需要析构函数.(当析构函数执行时,您无法确定托管对象是否仍然存在,因此无论如何都无法调用其Dispose方法.)
如果类只有非托管资源,则需要实现IDisposable,并且在程序不调用Dispose时需要析构函数.
Dispose方法必须安全运行多次.您可以通过使用变量来跟踪它之前是否已运行来实现.
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);
}
// 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;
// We don't need the destructor because
// our resources are already freed.
GC.SuppressFinalize(this);
}
}
}
Run Code Online (Sandbox Code Playgroud)
终结器用于隐式清理 - 每当一个类管理绝对必须清理的资源时你应该使用它,否则你会泄漏句柄/内存等......
正确地实现终结器是非常困难的,应尽可能避免 - SafeHandle类(在.Net v2.0及更高版本中)现在意味着您很少(如果有的话)需要再实现终结器.
该IDisposable接口用于显式清理并且更常用 - 您应该使用它来允许用户在完成使用对象时显式释放或清理资源.
请注意,如果您有终结器,那么您还应该实现该IDisposable接口,以允许用户比对象被垃圾收集时更快地显式释放这些资源.
请参阅DG更新:处理,完成和资源管理,我认为这是关于终结器和最佳建议的最佳和最完整的建议IDisposable.