を実装するクラスでIDisposable
は、オブジェクトが破棄されているかどうかを確認し、破棄されている場合はスローするのObjectDisposedException
はいつですか? すべてのパブリック メソッドとプロパティ (を除くDispose
) で? 時々?一度もない?
5 に答える
そのチェックは、破棄されたオブジェクトで機能しないメソッドでのみ実装する必要があります。
例:
クラスが でデータベース接続またはファイル ハンドルを閉じる場合、Dispose
それらのデータベース接続またはファイル ハンドルを必要とするすべてのメソッドは、インスタンスが既に公開されているかどうかを確認する必要があります。
オブジェクトが IsDisposed をサポートしている場合、そのメソッド自体は決してスローされません。IsDisposed が true を返す場合、他の多くのメソッドがスローするのが適切ですが、IsDisposed ではなく、それらのメソッドによって例外が生成される必要があります。オブジェクトが破棄された場合にスローされるユーティリティメソッド AssertNotDisposed があるかもしれませんが、そのような動作はその名前のメソッドから予想されます。
それ以外の場合は、オブジェクトに IDisposable オブジェクトを保持させ、有用な状態を維持しながら内部オブジェクトを Dispose できると便利な場合が多いことをお勧めします。たとえば、ユーザーから情報を取得するためにモードレス ダイアログ ボックスを表示および維持する機能を持つオブジェクトは、ボックスが閉じられた後でも、フィールドの内容のコピーを保持しておくと便利です。このようなオブジェクトは、内部の Disposable オブジェクトを Dispose しますが、有用な状態を維持する「Close」メソッドを提供する必要があります。Close を呼び出す Dispose メソッドを持つこともできますが、フィールド プロパティをスローさせる "NoLongerValid" フラグを設定することもできますが、実際に値が追加されるとは思いません。
オブジェクトが破棄された後に有用な状態を保持できる多くのケースは、おそらく分割する必要があるクラスを示していることを認めます。たとえば、Font クラスはおそらく、非使い捨ての FontInfo クラス (フォントの説明を保持するが、GDI ハンドルを保持しない) と IDisposable ReadyFont クラス (FontInfo を継承し、GDI フォント オブジェクトをカプセル化する) に分割する必要があります。フォントを使用するルーチンは、与えられたオブジェクトが FontInfo か ReadyFont かをチェックできます。前者の場合、GDI フォントを作成して使用し、リリースすることができます。後者の場合、ReadyFont の GDI フォント オブジェクトを使用して解放することができます。ReadyFont の作成者は、そのクリーンアップを確実にする責任があります。
そのままでは、コントロールをレンダリングするときにシステムがコントロールの Font プロパティに関連付けられた GDI オブジェクトを使用しようとするかどうかはわかりませんが、Font が Disposed の場合 (以前に Disposed であっても) 鳴らないことはわかっています。 Font プロパティに割り当てます!)。コントロールは、必要に応じて新しい GDI フォントを作成できます。彼らが常に新しい GDI フォントを作成するのか、それとも古いフォントが破棄された場合にのみ作成するのかはわかりません。前者の動作はよりパフォーマンスが高いように見えますが、慎重にコーディングしないと、別のスレッドがフォントを使用しているときにあるスレッドがフォントを破棄しようとした場合に問題が発生する可能性があります。
実際に指定されている唯一のことは、public void Dispose()
それ自体が何もスローしてはならないということです。
また、(非) 管理対象リソースを必要とするメソッドはスローする必要があります。
私の考えでは、議論の余地のあるケースはほんのわずかです。
- IsOpen、IsDisposed: スローしません
- その他 IsSomeStatus: 場合によります。
- Length、Count、Position : 閉じたストリームには長さがあるとは思わないので、投げます
クラスが StreamやCollectionなどの (関連のない) 関数を組み合わせると、さらに難しくなります。私たちはそれをすべきではありません。
破棄されたオブジェクトの使用は、できるだけ早く見つけたいプログラミング エラーです。
チェックする場所が多いほど、エラーをより早く見つけることができます。
ユーザーを混乱させないように、破棄されたオブジェクトが他の種類の例外 (ヌル ポインターなど) を引き起こす場所を必ず確認する必要があります。
他の場所では、努力する価値があるかどうかはアプリケーションに依存します。
おっしゃるとおり、Dispose と IsDisposed を除くすべてのパブリック メソッドとプロパティにこのチェックを実装します。これは、開発者が型がまだ有効であるという誤った印象で型を使用するのを防ぐための標準的なパターンです。