这是IDisposable

时间:2015-09-03 10:48:36

标签: c# architecture finalizer disposable

IDisposable模式实施起来很昂贵。在开始实际处理资源之前,我已计算了17行代码。

Eric Lippert最近写了一篇blog post提出了一个有趣的观点:任何时候终结者都会运行,这是一个错误。我觉得这很有道理。如果始终遵循IDisposable模式,则应始终抑制Finalizer。它永远不会有机会跑。如果我们接受终结器运行是一个错误,那么有一个指导方针迫使开发人员从以下抽象类派生并禁止直接实现IDisposable接口。

public abstract class AbstractDisaposableBase: IDisposable
{
    ~AbstractDisaposableBase()
    {
        ReportObjectLeak();
        Dispose(false); 
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected abstract void Dispose(bool disposing);

    [Conditional("DEBUG")]
    private void ReportObjectLeak()
    {
        //Debug.Assert(false, "leaked instance");
        //throw new Exception("leaked instance");
    }
}

好处很明显:

  1. 实施dispose变得简单且无错误,如下所示:
  2. class MyClass1 : DisablableBase { protected override void Dispose(bool disposing) { //dispose both managed and unmamaged resources as though disposing==true } }
    1. 未处理对象报告

    2. 始终遵循一次性模式

    3. 但是,这样的指南有什么问题吗?

      一个可能的问题是所有一次性物体都将定义一个终结器。但由于终结器总是受到抑制,因此不应该有任何性能损失。

      你有什么想法?

2 个答案:

答案 0 :(得分:4)

  

有一个指导方针来迫使开发人员从以下抽象类派生

不,仅仅是因为C#没有多重继承。接口描述行为,继承指示" is-a"。如果您强制执行此规则,您将彻底限制类的面向对象设计。

例如,您不能为非一次性的业务对象引入基类,派生类就是这样。

答案 1 :(得分:0)

  

但由于终结者总是被压制,所以不应该有任何性能损失。

IllegalArgumentException子类的实例仍将参与最终化队列管理,因此会对此产生性能影响。