当我们没有析构函数时,为什么我们应该调用SuppressFinalize
我有几个问题,我无法得到正确的答案。
1)当我们没有析构函数时,为什么我们应该在Dispose函数中调用SuppressFinalize。
2)Dispose和Finalize用于在对象被垃圾收集之前释放资源。 无论是托管资源还是非托管资源,我们需要释放资源,那么为什么我们需要在dispose函数内部存在一个条件,当我们从IDisposable调用这个重写函数时传递'true':Dispose并在从finalize调用时传递false。
看到我从网上复制下面的代码。
class Test : IDisposable
{
private bool isDisposed = false;
~Test()
{
Dispose(false);
}
protected void Dispose(bool disposing)
{
if (disposing)
{
// Code to dispose the managed resources of the class
}
// Code to dispose the un-managed resources of the class
isDisposed = true;
}
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
}
如果我删除了布尔保护的Dispose函数并执行如下操作。
class Test : IDisposable
{
private bool isDisposed = false;
~Test()
{
Dispose();
}
public void Dispose()
{
// Code to dispose the managed resources of the class
// Code to dispose the un-managed resources of the class
isDisposed = true;
// Call this since we have a destructor . what if , if we don't have one
GC.SuppressFinalize(this);
}
}
我在这里出门,但是......大多数人不需要全面的处置模式。 它被设计成在直接访问非托管资源(通常通过IntPtr
)和面对继承时是坚实的。 大多数时候,这些都不是必需的。
如果你只是持有其他实现IDisposable
的引用,那么你几乎肯定不需要终结器 - 无论是直接持有资源都负责处理这个事件。 你可以用这样的东西做:
public sealed class Foo : IDisposable
{
private bool disposed;
private FileStream stream;
// Other code
public void Dispose()
{
if (disposed)
{
return;
}
stream.Dispose();
disposed = true;
}
}
请注意,这不是线程安全的,但这可能不会成为问题。
通过不必担心子类直接持有资源的可能性,您不需要禁止终结器(因为没有终止器) - 而且您也不需要提供定制处置的子类方法。 没有继承,生活更简单。
如果你确实需要允许不受控制的继承(即你不愿意打赌子类将有非常特殊的需求),那么你需要去完整的模式。
请注意,使用.NET 2.0中的SafeHandle
,更需要您自己的终结器而不是.NET 1.1中的终结器。
为了解决你为什么首先有一个disposing
标志的问题:如果你在一个终结器中运行,你引用的其他对象可能已经完成。 你应该让他们自己清理,而且你应该只清理你直接拥有的资源。
保留第一个版本,更安全,并且正确实施处置模式。
调用SuppressFinalize
告诉GC你已经完成了所有对你的类的资源的破坏/处置,并且它不需要调用析构函数。
如果使用你的类的代码已经调用了dispose,并且你不应该告诉GC再次处理,你需要测试。
请参阅此MSDN文档(Dispose方法应调用SuppressFinalize)。
这里是主要的事实
1)Object.Finalize是你的类在有Finalizer时覆盖的内容。 〜TypeName()析构函数方法只是'override Finalize()'等的简写
2)如果在最终确定之前(例如,从使用块等出来的时候)在Dispose方法中处理资源,则调用GC.SuppressFinalize。 如果你没有Finalizer,那么你不需要这样做。 如果你有一个Finalizer,这可以确保该对象从Finalization队列中取出(所以我们不会处理东西两次,因为Finalizer通常也调用Dispose方法)
3)您将Finalizer实施为“故障安全”机制。 终结器保证运行(只要CLR没有中止),所以它们允许你确保代码在Dispose方法未被调用的情况下得到清理(可能程序员忘记在'using'中创建实例,块等
4)终结器是昂贵的,因为类型的终结器无法在Generation-0集合中进行垃圾收集(效率最高),并通过F-Reachable队列中的引用将其提升为Generation-1,以便它们代表GC根。 直到GC执行一个第一代集合,终结器被调用,并且资源被释放 - 所以只有在非常重要的时候才实现终结器 - 并且确保需要最终化的对象尽可能小 - 因为所有可以被你的可终结对象达成的也将被提升到第一代。
链接地址: http://www.djcxy.com/p/54321.html上一篇: Why should we call SuppressFinalize when we don't have a destructor