c# - DRY ID一次性图案

标签 c# design-patterns dry idisposable

我的很多类都重复下面的代码来实现 IDisposable。这似乎违反了 DRY(Don't Repeat Yourself)原则。我可以通过创建 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 模式?

最佳答案

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

此外,IDisposable 在我们讨论类型层次结构时会出现问题。
如果您认为派生类需要释放资源,一种常见的情况是将 IDisposable 粘贴到基类甚至接口(interface)上。然而,大多数时候,这只是一个假设,它实际上取决于实际的实现是否需要资源清理,从而使接口(interface)成为一个有漏洞的抽象。
如果类确实需要接口(interface),最好只实现接口(interface)。
但这有其自身的问题:
某个接口(interface)的消费者应该如何知道他得到的具体实例——例如作为构造函数参数——需要被释放?他将不得不明确地检查它。他基本上必须为他收到的每个非密封类型的每个实例执行此操作。

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

但是,如果你真的需要实现这个接口(interface),你应该遵循 this CodeProject article 描述的一次性设计模式。 .

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

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

关于c# - DRY ID一次性图案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18361535/

相关文章:

c# - SharePoint:如何以编程方式将附件添加到列表项?

excel - 识别单词中的模式

c# - 在存储库模式中加载子记录

c# - getter 和 setter 中的冗余代码

c# - 是否可以在 Android 上部署 Silverlight 应用程序?

c# - GridView 查询不显示

c# - 如何使用 linq 和 c# 根据列中行之间的差异进行分组?

design-patterns - Yegge 的原型(prototype)模式示例如何处理实例变量?

javascript - 如何通过控制台记录整个 HTML 表单?

prolog - Prolog 中的 DRY 算术表达式求值