1

インターフェイスを持つクラスがありIDisposableます。どの動作を実装すればよいかわかりません。Dispose メソッドの後にこのクラスの for each メソッド呼び出しをスローする必要がObjectDisposedExceptionありますか?それとも、破棄されたリソースへのデータ アクセスなどの指定されたメソッドでのみ例外をスローする必要がありますか?

私はBitmapオブジェクトをテストしました(ほんの一例):

Bitmap b = new Bitmap (100, 100);
b.Dispose (); // if i remove this line - console will display: Format32bppArgb
Console.WriteLine (b.PixelFormat);
Console.ReadKey ();

コンソール表示: DontCare

したがって、例外はスローされていません。Dispose を呼び出した後、Bitmap オブジェクトで PixelFormat プロパティを使用できるようになりました。この振る舞いに従うべきですか?

4

3 に答える 3

1

破棄されたリソースへのデータアクセスなど、指定されたメソッドでのみ例外をスローする必要がありますか?

これは自動です。ファイナライザーを持つクラスは、このような場合にスローする必要があります。結局のところ、このメソッドは、もはや生きていないオペレーティング システム オブジェクトにアクセスするため、エラーが発生します。オペレーティング システムのエラー コードによって生成される不可解なものではなく、ObjectDisposedException のような明確なもので報告することをお勧めします。

あなたが与えたビットマップの例は非常に悲しいものですが、GDI+ クラスでは珍しいことではありません。一般に、エラー処理は非常に貧弱です。これは例ではありません。

前の段落のキー フレーズは、「ファイナライザーを持つクラス」でした。あなたのクラスにはファイナライザーがあってはならないので、カプセル化する使い捨てクラスのメソッドに任せるのではなく、自分自身をスローするかどうかは議論の余地があります。一般に、これは避けるべきです。実際のメリットがほとんどないため、コードが乱雑になる傾向があります。しかし、悪いデータを返す Bitmap のような厄介なクラスをラップする場合は、遠慮なくそうしてください。

于 2013-02-03T01:31:31.327 に答える
1

この問題や他の多くの問題に関する私の哲学は、「理にかなったことをする」ことです。

場合によっては、クラスがそのリソースを解放した後に特定のクラス メンバーを使用することが非常に合理的な場合があります。実際、一部のシナリオではそのような使用が必要になる場合があります。たとえば、オブジェクトがネットワーク接続を介して非同期トランザクションを管理している場合、シャットダウンするように要求し、シャットダウンした後、処理されたトランザクションの数、ぶら下がっているトランザクションが残っていないかなどを尋ねます。このような統計の値は、シャットダウンが完了するまで知ることができず、概念的には、オブジェクトにシャットダウンを要求してから、オブジェクトが既に実行したことに関する履歴情報を要求することに問題はありません。

Close歴史的な情報を報告するプロパティの使用を許可する一方で、接続をシャットダウンする必要があると主張する人もいるかもしれませんがDispose、物事をシャットダウンしてそのようなプロパティの使用を禁止する必要がありますが、私はそのような区別は役に立たないと考えています. とりわけ、接続がそれに関連付けられているすべてのリソースを解放することを望む場合があります ( Close「再開」要求を許可するために、何かが実行を控える場合があります)。さらに、 と の間に他に動作の違いがない場合、純粋に 2 つの別個のメソッドを必要とする必要はないと思うのでClose、統計データが無効になる可能性があります。DisposeDispose

ある意味では、多くのIDisposableオブジェクトは、外部リソースと対話するエンティティと、マネージ コードと対話し、それ自体で機能が制限されている可能性があるエンティティの 2 つの部分を持つと見なすことができます。「関心の分離」の原則は、2 つの部分を別々のオブジェクトにすることを示唆していますが (実際、そのような分割が役立つ場合があります)、多くの場合、クライアント コードは単一の参照を保持する必要があります。両方の目的を果たします。その参照は を実装するIDisposable必要がありますが、破棄によってマネージ コード側が破壊されることはありません。

例として、WinFormsFontクラスを考えてみましょう。このクラスは、(1) フォントに関する情報のコレクション (書体、サイズ、スタイルなど)、および (2) GDI フォント ハンドルの 2 つをカプセル化します。aFontDisposed の場合、テキストの描画には使用できなくなりますが、書体やスタイルなどは忘れられませんDispose。d フォントが与えられた場合、古いフォントの情報を使用して新しいフォントを構築することができます。残念ながら、そのような情報を読み取ることを可能にするプロパティのほとんどは、 によって明示的に無効化されてDisposeいます。つまり、多くの場合、既存のものに似ているが廃棄されFontているが、いくつかの変更を加えたフォントを作成したい場合は、古いフォントから情報をコピーして新しいフォントを構築し、そのフォントに基づいて別の新しいフォントを構築し、Dispose最初に作成された新しいフォント。フォントの説明を保持したいがFontDescriptionGDI ハンドルを必要としない場合に、フォントの説明を-使い捨てクラスですが、それはクラスの設計方法ではありません。

于 2013-02-03T00:18:37.497 に答える
0

dispose を呼び出した後、objectto を設定するのnullが、私が通常従うアプローチです。次に、null 例外がスローされるため、例外を作成する必要はなく、適切な方法のようです。

オブジェクトが null の場合、オブジェクトは破棄されるため、null であるかどうかは問題ではありません。または、初期化されていないため null であるか、明示的に null に設定されているため null です。コンシューマーは、null であるという基本的なアクションではなく、それが null であることを認識している必要があります。

于 2013-02-02T07:04:07.030 に答える