8

IDisposable 模式的实现成本很高。在开始实际处理资源之前,我已经计算了 17 行代码。

Eric Lippert 最近写了一篇博客文章,提出了一个有趣的观点:任何时候运行终结器,它都是一个错误。我认为这很有意义。如果始终遵循 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 变得容易且无错误,如下所示:

class MyClass1 : DisablableBase { protected override void Dispose(bool disposing) { //dispose both managed and unmamaged resources as though disposing==true } }
  1. 报告了未处理的对象

  2. 始终遵循一次性模式

但是,这样的指导方针有什么问题吗?

一个可能的问题是所有一次性对象都将定义一个终结器。但是由于终结器总是被抑制,所以不应该有任何性能损失。

你觉得呢?你有没有什么想法?

4

2 回答 2

4

有一个指导方针来强制开发人员从以下抽象类派生是否有意义

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

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

于 2015-09-03T12:33:23.833 回答
0

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

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

于 2015-09-03T12:47:51.870 回答