2

私は、人気のあるMediaInfo ライブラリを .NET で使いやすくする OSS プロジェクトに取り組んでいますが、この質問は一般化できます。

派生クラスDが、その基本クラスDBのコンストラクターを呼び出すときに常にオブジェクトOをインスタンス化する場合。DB はその値をコンストラクターに送信された値に設定しますが、値自体はDBの基本クラスBで宣言されています。

  1. 誰がO (以下のコードの AKA mediaInfo)を「所有」していますか?
  2. .NET アプリケーションの場合、IDisposable を実装する必要があるのはどれですか? 注: Oは管理されていないか、少なくとも管理されていないライブラリにラップされた管理オブジェクトのインスタンス化ですが、「MediaInfo.Close();」の形式でクリーンアップする必要があります。これが「管理されていない」と見なされるかどうかはわかりません。

わかりやすくするために、実際のコードを使用してみましょう。

DはDBから派生します。

// MediaFile is "D" 
public sealed class MediaFile : GeneralStream
{
    public MediaFile(string filePath)
        : base(new MediaInfo(), 0) {
        // mediaInfo is "O"
        mediaInfo.Open(filePath);
    }
}

DBは、 Bから派生した継承されたOを設定します。

// GeneralStream is "DB"
public abstract class GeneralStream : StreamBaseClass
{
    public GeneralStream(MediaInfo mediaInfo, int id) {
        this.mediaInfo = mediaInfo; // declared in StreamBaseClass
        // ...
    }
}

BはOを宣言します。

// StreamBaseClass is "B"
public abstract class StreamBaseClass
{
    protected MediaInfo mediaInfo; // "O" is declared
    // ...
}
4

3 に答える 3

2

リソースへの参照を保持するオブジェクトがそれを所有します。

StreamBaseClass参照がmediaInfoあり、実装する必要がありますIDisposable。参照とDisposeメソッドは、派生クラスによって自動的に継承されます。

于 2012-03-11T18:30:37.983 に答える
1

クラス C が、IDisposable を実装する公開されていないローカル変数 V である変数を所有している場合、C は IDisposable であり、C の IDisposable は V を破棄する必要があります。

クラス D がネイティブ リソース N を所有している場合、D は IDisposable (N を削除する) である必要があり、N を解放するために自身で Dispose() を呼び出すファイナライズ可能なデストラクタも必要です。

このパターンに従う場合、IDisposable がある場合は、完了したら常に Dispose() を実行する必要があります。これにより、オブジェクト ツリーのすべてが削除されます。しかし、誰かが忘れた場合 (同僚、ライブラリのユーザーなど) がオブジェクトをリークすることはありません。これは、ネイティブ リソースが D のファイナライザーによってクリーンアップされるためです。

于 2012-03-11T18:30:05.940 に答える
1

の責任は、明示的な同意がない限り、それを作成IDisposableしたオブジェクトに属します。逆契約は、一般に、リソースの作成者が消費者の寿命をまったく知らない場合に使用されます。多くの場合、コンストラクターまたはファクトリ メソッドが、渡された の最後のコンシューマーとなる可能性があるものを生成している場合、そのメソッドは、 を呼び出す責任を受け入れるかどうかを示すパラメーターを受け入れるか、コールバック デリゲートを受け入れる必要があることをお勧めします。 、null でない場合、コンシューマーがオブジェクトを必要としなくなったときに呼び出されます。オブジェクトの作成者が消費者よりも長生きする場合は、null を渡すことができます。オブジェクトが渡された後、作成者がそのオブジェクトを使用できなくなる場合は、オブジェクトのIDisposableDisposeDispose方法。作成者は、それが消費者よりも長生きするかどうかわからない場合、オブジェクトがまだ必要かどうかを判断し、Disposeそうでない場合に呼び出すメソッドを渡すことができます。

あなたの特定のケースに関してIDisposableは、チェーンされたコンストラクター呼び出し内で を構築することは、リソースリークのレシピです(try-finallyブロックでチェーンされたコンストラクター呼び出しをラップする方法がないため)。何らかの方法でそれを安全に処理する場合 (たとえば、チェーン コンストラクターではなくファクトリ メソッドを使用するか、[threadstatic]ハックを使用するなど)、オブジェクト (派生クラス) の作成者はオブジェクトの有効期間を知っているので、それをお勧めします。消費者 (基本クラス)、所有権、およびクリーンアップの責任は、オブジェクトの作成者にある必要があります。

于 2012-03-12T18:47:01.430 に答える