22

罪のない人を保護するために、クラス名が変更されました

ISomeInterface という名前のインターフェイスがあるとします。インターフェイスを継承するクラス FirstClass と SecondClass もあります。FirstClass は、破棄する必要のあるリソースを使用します。SecondClass はそうではありません。

問題は、IDisposable からどこを継承する必要があるかということです。次のオプションはどちらも理想的とは言えません。

1) FirstClass に IDisposable を継承させます。次に、ISomeInterfaces を扱うコードは、それらを破棄するかどうかを知る必要があります。これは私には密結合のようなにおいがします。

2) ISomeInterface に IDisposable を継承させます。次に、それを継承するすべてのクラスは、破棄するものがない場合でも、IDisposable を実装する必要があります。Dispose メソッドは、コメント以外は基本的に空白です。

#2は私にとって正しい選択のように思えますが、代替案があるかどうか疑問に思っています.

4

6 に答える 6

19

抽象エンティティ (インターフェイスまたは抽象クラス)を破棄する必要がある可能性が十分にある場合は、それを実装する必要があります。Stream、たとえば、それ自体は を必要とせず、 ...IDisposableも必要としませんIEnumerator<T>

Dispose()抽象基本クラスは、 then のデフォルト (空の) 実装と、おそらくファイナライザー / Dispose(bool) パターンを持つことができるため、より単純になる可能性があります。

~BaseType() => Dispose(false);

protected virtual void Dispose(bool disposing) 
{
}

void IDisposable.Dispose() 
{ 
    Dispose(true); GC.SuppressFinalize(this); 
}
于 2009-12-02T16:55:08.523 に答える
3

ISomeInterface の一部の実装で破棄が必要であることがわかっている場合は、インターフェイスの具体的な実装に破棄するものがなくても、インターフェイスは IDisposable を継承する必要があります。

たとえば、BCL では、IDataReader は IDisposable を実装しますが、破棄する必要のある外部リソースを持たないデータ リーダーの実装は確かに想像できます。

于 2009-12-02T16:56:09.040 に答える
2

これまでに書かれたすべての答えは重要なポイントを見逃しています。基本クラスのインスタンスを期待するコードが、気付かずに破棄を必要とするインスタンスの所有権を取得するIDisposable可能性がある場合にのみ、基本タイプまたは基本インターフェースを実装する必要があります。これが発生する可能性のある最も一般的なシナリオは、ファクトリメソッドを使用する場合です。代表的な例は/です。ほとんどの列挙子はクリーンアップを必要としませんが、呼び出すコードには通常、返された列挙子が実際にクリーンアップを必要とすることや、必要としないことを信じる特別な理由はありません。一般に、実装のすべての実装を持ち、すべての消費者に電話をかける方が速いです。IEnumerable<T>IEnumerator<T>IEnumerable<T>.GetEnumeratorIEnumerator<T>IDisposableDispose返された列挙子で、返された型が実装されているかどうかをコンシューマーに確認させ、実装されIDisposableている場合はそれを呼び出すよりも。

基本タイプの参照は、通常、問題のアイテムのクリーンアップを担当しないメソッドによってのみ使用されることが予想される場合、基本タイプを実装する必要はありませんIDisposable。クリーンアップを担当するコードは、処理しているオブジェクトがIDisposable、基本タイプが実装しているかどうかに関係なく実装されていることを認識します。

于 2012-09-27T20:59:52.983 に答える
2

インターフェースにもよりますが、私は #2 に傾倒します。の 2 つの実装がISomeInterfaceあり、そのうち 1 つだけを破棄する必要がある場合は、リファクタリングが必要になる可能性があります。

一般に、インターフェイスにバインドする場合はIDisposable、基本クラスではなく、そのインターフェイスを継承する方が適切です。インターフェイスが を継承しない場合は、オブジェクトを破棄するためにIDisposableキャストする必要がIDisposableあり、InvalidCast のリスクが発生します...

于 2009-12-02T16:57:32.950 に答える
2

すべてのコードで ISomeInterfaces を一般的に処理する場合は、はい、それらはすべて使い捨てにする必要があります。

そうでない場合は、FirstClass を作成するコードで破棄する必要があります。

using (FirstClass foo = new FirstClass()) {
    someObjectThatWantsISomeInterface.Act(foo);
}

それ以外の場合は、次の拡張メソッドのようなものをいつでも使用できます。

public static void DisposeIfPossible(this object o) {
    IDisposable disp = o as IDisposable;
    if (disp != null)
        disp.Dispose();
}

// ...
someObject.DisposeIfPossible(); // extension method on object

また、これにはテンプレート基本クラスのアプローチを好むことにも言及する必要があります。使い捨てのものを適切に構築することについて、このブログでこれをスタブしました。

于 2009-12-02T17:00:29.683 に答える
1

私のアドバイスは、具象クラスに直接ではなく、ルートに移動することです。ポイント 2 は根本的なものであり、FirstClass によるある種の契約によって駆動されます。クラスが何らかのインターフェイスを実装する必要があることがわかっている場合は、インターフェイスが IDisposable を継承するコントラクトに署名することを確認する必要があります。

于 2009-12-02T16:56:18.367 に答える