【问题标题】:Removing old-fashioned finalizers删除老式的终结器
【发布时间】:2014-03-23 12:03:45
【问题描述】:

在一个将近 10 年历史的系统中,我已经实现了几个 IDisposable 实现。回到过去,当我还年轻但还很愚蠢的时候,趋势是也实现终结器:

class MyClass: IDisposable
{
    public void Dispose() { Dispose(true); }
    ~MyClass { Dispose(false); }

    private void Dispose(bool bDisposing)
    {
         ... dipose  ...
         if(bDisposing)
             GC.SupressFinalize(this);
    }
}

终于,在将近十年之后,这让我们感到困惑 - Dispose 方法在从终结器调用时抛出了异常,并且进程在没有警告的情况下意外终止。

我想删除所有终结器,只保留将处理资源的 Dispose 方法。是否有任何理由保留终结器?没有一个对象使用非托管资源,所以我很确定我不会得到资源泄漏。对吧?

【问题讨论】:

  • Dispose 方法在从终结器调用时引发了异常:我认为这不是真的,因为当它从 Dispose 方法中抑制 Finalizer 时使用true 参数调用。
  • “没有一个对象使用非托管资源” - 那么你为什么首先实现 IDisposable 呢?另外,看看这个问题:stackoverflow.com/q/3882804/1974021
  • 我实现了 IDisposable 让人们编写 using(new MyObj())... 并在离开 using 块时运行清理代码。
  • 我们遇到的问题是IDisposable接口的构造函数抛出了异常,所以没有调用Dispose,而finalizer又抛出了一个异常……

标签: c# memory-management garbage-collection finalizer disposable


【解决方案1】:

关于何时需要终结器的一般建议是:几乎从不。请参阅 Eric Lippert 对以下问题的回答:

When should I create a destructor?

您的应用程序是否会发生泄漏取决于很多因素。但是,如果您没有非托管资源,并且您擅长 Dispose'ing 应该被释放的类,那么您就不应该有泄漏。

关于您上面关于遇到终结器在未完全构造的对象上运行的问题的评论:这是终结器可能是危险事物的部分原因。编写一个正确的终结器是一件非常困难的事情。如果您确实有必须始终清理的资源,则应该使用 SafeHandle:

http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.safehandle(v=vs.110).aspx

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-03-20
    • 2012-04-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多