管理されていないリソースを「所有する」クラスは、(そしてIDisposableを実装する)?
-
11-12-2019 - |
質問
私は OSS Project に働いています< href="http://mediainfo.sourceforge.net/en" rel="nofollow"> mediainfoライブラリ .NETで使いやすいですが、この質問は一般化できます。
派生クラス d が常にその基本クラス db のコンストラクタを呼び出すときにオブジェクト o をインスタンス化します。 DBはそのコンストラクタに送信されたものに値を設定しますが、値自体は db の基本クラス b :で宣言されています。
- 「所有」 (下のコードのAKA Mediainfo)?
- .NETアプリケーションの場合、これらのうちどれがIDSposableを実装する必要がありますか?
注: 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 宣言 :
.// StreamBaseClass is "B" public abstract class StreamBaseClass { protected MediaInfo mediaInfo; // "O" is declared // ... }
解決
リソースへの参照を保持するオブジェクトを所有しています。
StreamBaseClass
は参照mediaInfo
を持ち、IDisposable
を実装する必要があります。参照とDispose
メソッドは自動的に派生クラスによって継承されます。
他のヒント
クラスCがIDSPOOSABLEを実装する非公開ローカル変数Vである変数を所有している場合、CはIDSPOOSABLEであり、CのIDSPOOSABLEはvを配置する必要があります。
クラスDがネイティブリソースnを所有している場合、dはIDSPOOSABLE(n)とでもにを持ちます。P>
このパターンをたどる場合は、IDSPOOSABLEを持つことがある場合は、常に()を廃棄する必要があります()、それはオブジェクトツリーのすべてをすべて削除します。しかし、誰かがあなたを忘れた場合にも(読み取り:同僚、あなたのライブラリーのユーザーなど)ネイティブリソースはD'Sファイナライザーによってクリーンアップされるため、オブジェクトを漏らすことはありません。
IDisposable
の責任は、がが作成するオブジェクトに属します。特に明示的な契約がない場合は、が作成します。逆の協定は、一般に、リソースの作成者が消費者の存続期間についてはわからない場合に使用されます。 ConstructorまたはFactoryメソッドが渡されたIDisposable
の最後の消費者になる可能性がある場合、そのメソッドがDispose
の呼び出しを受け入れるかどうかを示すパラメータを受け入れるべきです。 NULL以外の場合、消費者がオブジェクトが必要なときに呼び出されます。オブジェクトの作成者が消費者を表示する場合は、NULLを渡すことができます。それがハンドオフされた後にCreatorがオブジェクトに使用されない場合は、オブジェクトのDispose
メソッドを渡すことができます。 Creatorが消費者を示すかどうかわからない場合は、オブジェクトがまだ必要かどうかを判断し、そうでない場合はDispose
を呼び出すメソッドを渡すことができます。
チェーンコンストラクターの中にIDisposable
を構築することは、コールのレシピです(Try-Lock In Try-Lockで連鎖コンストラクタコールをラップする方法はありません)。あなたが何か安全にハンドルすること(例えば、連鎖コンストラクタではなく、または[threadstatic]
Hackを使用することによって)それをハンドルすることになっていた場合、私はオブジェクトの作成者(派生クラス)がの一生を知ることになることを提案するでしょう。消費者(基本クラス)、所有権、およびクリーンアップの責任は、オブジェクト作成者に留まるべきです。