廃棄可能なインスタンスをカプセル化するよりもクラスに対処する方法は?
-
14-10-2019 - |
質問
interface IMyInterace
{
void Open();
object Read();
void Close();
}
class MyImplementation : IMyInterface
{
public void Open() { /* instantiates disposible class */ }
//...
public void Close() { /* calls .Dispose(); */ }
}
このタイプの状況に対処して、クラス内の廃棄可能なインスタンスが呼び出されるようにする良い方法はありますか? (ドキュメントを除いて「閉じる」と呼ばなければならないという発信者に信号はありません。)IMYINTERFACEの実装は、必ずしもイディジーインスタンスをカプセル化するわけではなく、アプリケーションの寿命を通じて閉じられ、繰り返し再開されます。
私はこれをすることを考えています:
- myimplementationでidisposibleを実装します。
- dispose()を設定してClose()を呼び出します。
- close()に呼び出しを追加するか、以前の呼び出しが閉じられていることを確認するために、close()またはdose()を開始します。
IMYINTERFACEのユーザーは、使用している実装がわからないため、Myimplementationがどれだけの価値があるかはわかりません。また、すべての実装がIdisposiblesをカプセル化するわけではありません。
解決
ここですでに答えに加えて:
このクラスが(多くの場合/時には)インターフェイスだけで使用されている場合は、ImyinteraceをIdisposableから継承するようにアドバイスします。
これにより、ユーザーはこれらのオブジェクトを一貫した方法で使用できます。欠点は、もちろん、実際にそれを必要としないクラスにメソッドを処分する(ダミー)追加する必要があるかもしれないことです。しかし、利点は一貫性と柔軟性にあります。クラスが将来変化して廃棄()が必要な場合はどうなりますか?
最小限のアプローチ:
interface IMyInterace : IDisposable { }
sealed class MyImplementation : IMyInterface
{
public void Open() { /* instantiates disposible class */ }
public void Close() { /* calls _myField.Dispose(); */ }
public void Dispose() { Close(); } // only use this short form in a sealed class
}
他のヒント
これを処理する標準的な方法は、単に持っていることです MyImplementation
埋め込む IDisposable
.
ジョンが述べたように、あなたの最初の箇条書きはすぐにあります。
時々a Close()
メソッドは機能的に同義です Dispose()
, 、および抽象化とセマンティックの一貫性を維持するために存在します。つまり、補完するために Open()
方法。別の時に、 Close()
再び開くことができますが Dispose()
いけない。したがって、2番目の箇条書きも問題ありません。
廃棄されたオブジェクトを再利用してはならないため、箇条書き3は必ずしも適用されるわけではありません。電話する必要がある場合 Open()
繰り返しますが、新しいインスタンスを使用する必要があります。実際、 Open()
メソッドはスローする必要があります ObjectDisposedException
一度 Dispose()
(プライベートをチェックすることで呼ばれています disposed
ブールフラグ)。オブジェクトを閉じる後の再オープンをサポートすることを望む場合は、使用することを検討するかもしれません Debug.Assert()
および/または例外をスローする場合 Open()
なしで呼ばれます Close()
. 。これは、これらのインスタンスのずさんな管理を防ぐのに役立ちます。
単にインターフェイスを実装するよりも複雑な完全な使い捨てパターンに従ってください。
bool disposed;
public void Dispose() // don't make virtual!
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if(!disposed)
{
if(disposing)
{
// dispose of managed resources here, for example:
// if(resource != null) { resource.Dispose(); }
}
}
// dispose of unmanaged resources here
disposed = true;
}