我可以在同一个类中实现这两个方法吗?
public class MyClass : IDisposable
{
// some implementation
// if i missed to call Dispose() method;
~MyClass()
{
// it means, clear all does not mananage resources
// but dont use Dispose() method
}
public void Dispose()
{
// clear resources
// if i call this method will i can do this:
GC.SuppressFinalize()
// it means dont use Finalizw method for this object
}
}
我是对的吗?因为我无法理解这个GC.SuppressFinalize()方法?
答案 0 :(得分:7)
是的,您可以按照自己的意愿实施这两种方法。
通常,如果对象可以同时具有托管和非托管引用,则正确的模式是:
public class MyClass : IDisposable
{
~MyClass()
{
Dispose(false);
}
public void Dispose()
{
GC.SuppressFinalize(this);
Dispose(true);
}
public virtual void Dispose(bool disposing)
{
if(disposing)
{
// clear MANAGED references
}
// free UNMANAGED resources
}
}
但您可以根据需要实现此功能。这只是一种模式。例如,如果您没有任何非托管资源并且您的类已被密封(因此您可以确定它不会使用任何非托管资源),您可以像以下一样实现它:
public sealed class MyClass : IDisposable
{
public void Dispose()
{
// release managed references
}
}
忘记终结者。
在第一个模式中,GC.SuppresFinalize(this)
正在做什么,告诉垃圾收集器在释放对象时不应该调用终结器(~MyClass()
方法):如果你专门调用了{{ 1}}然后你已经已经调用了你的虚拟Dispose()
函数,为什么要再次调用它?
问题是终结器本身在C#中是不确定的:你不知道什么时候会被调用...你甚至不能保证它甚至会被调用(尽管它会在正常清理期间,如果之前没有调用过),这就是Dispose(bool)
存在的原因,它是确定性释放托管引用的方式,释放对象,并释放和释放由分配的非托管资源它
如果GC正在释放某个对象,那么它所拥有的所有托管引用也将被释放,因此在调用终结器时无需清除托管引用。
但是,您的应用程序应尽最大努力释放和释放它拥有的任何非托管资源。
如果您忘记了IDisposable
,那么它们应该有最后一次机会被释放(当GC收集对象时,或者在应用程序运行时进行最后的清理)。在正常模式中你也可以实现终结器,并告诉它清理非托管资源如果你还没有完成它
请注意,与普遍看法相反,拨打Dispose()
并不特别,只是方法调用:如果您愿意,可以将其称为Dispose()
或FreeMyObject()
。它不会使垃圾收集器释放任何内存。使用FooBar()
有一个模式,非常重要的是它获得了自己的语言语法结构(IDisposable
块),但它只是一个模式。您可以执行与using
相同的操作,而无需执行Dispose()
。