当我们没有析构函数时,为什么我们应该调用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

    下一篇: Parallel Objects Initialization