3

我的很多类都重复下面的代码来实现 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 模式?

4

2 回答 2

3

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

此外,IDisposable当我们谈论类型层次结构时会出现问题。
如果您认为派生类需要释放资源,则常见的情况是坚持IDisposable使用基类甚至接口。然而,大多数时候,这只是一个假设,如果需要清理资源,它真的取决于实际的实现,这使得接口成为一个泄漏的抽象。
如果类真的需要它,最好只实现接口。
但这也有其自身的问题:
某个接口的使用者应该如何知道他得到的具体实例——例如作为构造函数参数——需要被释放?他必须明确地检查它。而且他基本上必须为他得到的每一种非密封类型的每一个实例都这样做。

这只是两个示例,它们表明您最好以一种不需要实现IDisposable.

但是,如果您确实需要实现此接口,则应遵循本 CodeProject 文章中描述的一次性设计模式。

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

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

我不认为你在这里违反了 DRY 原则。因为尽管您在每个班级都进行了处理,但实际上您并没有做同样的事情。,

于 2013-08-21T15:33:36.177 回答