干IDisisable模式

时间:2013-08-21 15:26:53

标签: c# design-patterns dry idisposable

我的很多课程重复以下代码来实现IDisposable。这似乎违反了DRY(不要重复自己)的原则。我可以通过创建一个AbstractDisposable基类来避免一些工作,但如果我需要扩展其他现有对象(假设这些对象本身不是一次性的),这似乎不合适/不会工作。

另一种选择是使用模板/元语言,我可以为每个类指定托管和非托管资源的列表,并在构建项目时自动生成通用的Dispose Pattern - 但到目前为止我还没有玩过元语言/这对于这种常见情况来说似乎极端。

public class SomeDisposableClass : IDisposable
{
    IDisposable _something; //a managed resource (unique to this class / here for illustration)

    /* ... loads of code unique to this class ... */

    #region Dispose Pattern
    private bool _disposed = false;

    ~SomeDisposableClass()
    {
        Dispose(false);
    }

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

    protected virtual void Dispose(bool disposing)
    {
        // Check to see if Dispose has already been called. 
        if (!this._disposed)
        {
            if (disposing)
            {
                // Dispose managed resources.
                if (this._something!=null) this._something.Dispose(); //(unique to this class / here for illustration)
            }
            // Clean up any unmanaged resources
            this._disposed = true;
        }
    }
    #endregion
}

有没有一种很好的方法可以在不违反DRY原则的情况下实现合适的Dispose模式?

2 个答案:

答案 0 :(得分:3)

我尽量避免IDisposable。问题是它遍布整个代码库。如果一个类有一个一次性成员,那个类也需要实现IDisposable等。

此外,当我们谈论类型层次结构时,IDisposable存在问题 如果您认为派生类需要释放资源,常见的情况是将IDisposable粘贴到基类甚至接口上。但是,大多数情况下,这只是一个假设,如果需要进行资源清理,它实际上取决于实际实现,使接口成为漏洞。 如果班级确实需要它,那么最好只实现界面 但这有其自身的问题:
某个界面的消费者应该如何知道他得到的具体实例 - 例如作为构造函数参数 - 需要处理?他必须明确检查它。而且他基本上必须为他所交付的每一种非密封类型的每个实例做这件事。

这些只是两个示例,表明您最好以某种方式设计类,以便它们不需要IDisposable的实现。

但是,如果您确实需要实现此界面,则应遵循this CodeProject article所述的一次性设计模式。

它基本上将您的类型分为两个级别:

  • 级别0:级别0的类仅包含非托管资源,不包含托管资源。这些类需要大多数常用的默认IDisposable模式,尽管您不必实现处理托管资源的部分。
  • 级别1:级别1的类仅包含级别0和级别1的受管资源。这些类仅需要IDisposable的简化实现,因为它们不包含非托管资源。该实现基本上只在每个Level 0和Level 1成员及其基类上调用Dispose

答案 1 :(得分:1)

我不认为你在这里违反DRY原则。因为虽然你在每个班级都在处理,但你基本上没有做同样的事情。,