3

私のクラスの多くは、以下のコードを繰り返して IDisposable を実装しています。これは、DRY (Don't Repeat Yourself) の原則に違反しているようです。基本クラスを作成することで一部の作業を回避できましたAbstractDisposableが、それは不適切なようです/他の既存のオブジェクトを拡張する必要がある場合は機能しません (それらのオブジェクト自体が使い捨てではないと仮定します)。

別のオプションは、テンプレート/メタ言語を使用して、クラスごとにマネージド リソースとアンマネージド リソースのリストを指定し、プロジェクトをビルドするときに汎用の Dispose パターンを自動生成することですが、これまでメタ言語で遊んだことはありません /これは、このような一般的なシナリオでは極端に思えます。

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ただし、ほとんどの場合、これは単なる仮定であり、リソースのクリーンアップが必要かどうかは実際の実装に依存し、インターフェイスが漏れやすい抽象化になります。
クラスが本当に必要とする場合にのみ、インターフェースを実装する方が良いでしょう。
しかし、これには独自の問題があります。
特定のインターフェイスの消費者は、取得した具体的なインスタンス (たとえば、コンストラクターのパラメーターとして) を破棄する必要があることをどのように知ることになっているのでしょうか? 彼はそれを明示的にチェックする必要があります。そして、彼は基本的に、彼が受け取ったすべての非封印型のすべてのインスタンスに対してこれを行う必要があります。

これらは、 の実装を必要としないような方法でクラスを設計するのが最善であることを示す 2 つの例にすぎませんIDisposable

ただし、このインターフェイスを本当に実装する必要がある場合は、この CodeProject の記事で説明されている使い捨てデザイン パターンに従う必要があります。

基本的に、タイプを 2 つのレベルに分けます。

  • レベル 0: レベル 0 のクラスには、管理されていないリソースのみが含まれ、管理されているリソースは含まれません。これらのクラスには、通常の既定のIDisposableパターンのほとんどが必要ですが、管理対象リソースを処理する部分を実装する必要はありません。
  • レベル 1: レベル 1 のクラスには、レベル 0 と 1 の両方のマネージド リソースのみがIDisposable含まれます。実装は基本的Disposeに、レベル 0 とレベル 1 の各メンバーとその基底クラスを呼び出すだけです。
于 2013-08-21T16:58:21.743 に答える