デストラクタではなく、クラスにIDisposeをいつ実装しますか? この記事 を読みましたが、まだポイントがありません。
私の前提は、オブジェクトにIDisposeを実装すると、ガベージコレクターが実行するのを待つのではなく、明示的に「破壊」できるということです。これは正しいです?
これは、オブジェクトに対してDisposeを常に明示的に呼び出す必要があるということですか?これのいくつかの一般的な例は何ですか?
ファイナライザ(デストラクタ)はガベージコレクション(GC)の一部です-GCが主にメモリ不足の結果として発生するため(つまり、より多くのスペースが必要)、これが発生する(または発生する場合でも)不確定です。管理対象リソースには独自の収集/廃棄があるため、ファイナライザは通常、unmanagedリソースのクリーンアップにのみ使用されます。
したがって、IDisposable
は決定論的にオブジェクトのクリーンアップに使用されます。オブジェクトのメモリ(まだGCに属している)を収集しませんが、たとえば、ファイル、データベース接続などを閉じるために使用されます。
これに関する多くの以前のトピックがあります。
最後に、IDisposable
オブジェクトにファイナライザーもあることは珍しくありません。この場合、Dispose()
は通常GC.SuppressFinalize(this)
を呼び出します。これは、GCがファイナライザを実行しないことを意味します-単にメモリを破棄します(はるかに安価です)。オブジェクトをDispose()
するのを忘れた場合、ファイナライザは引き続き実行されます。
Finalize()
メソッドの役割は、.NETオブジェクトがアンマネージリソースをクリーンアップできるようにすることですガベージコレクション時。ただし、ガベージコレクションに依存する代わりに、データベース接続やファイルハンドラなどのオブジェクトをできるだけ早く解放する必要があります。そのためには、IDisposable
インターフェイスを実装し、Dispose()
メソッドでリソースを解放する必要があります。
[〜#〜] msdn [〜#〜] には非常に優れた説明があります。
このインターフェイスの主な用途は、アンマネージリソースを解放することです。ガベージコレクターは、管理対象オブジェクトが使用されなくなると、管理対象オブジェクトに割り当てられたメモリを自動的に解放します。ただし、ガベージコレクションがいつ発生するかを予測することはできません。さらに、ガベージコレクターは、ウィンドウハンドルなどのアンマネージリソース、またはopen filesおよびストリーム。
このインターフェイスのDisposeメソッドを使用して、ガベージコレクタと一緒にアンマネージリソースを明示的に解放します。オブジェクトのconsumerは、オブジェクトが不要になったときにこのメソッドを呼び出すことができます。
C#デストラクタにあるべき唯一のものはこの行です:
Dispose(False);
それでおしまい。このメソッドには他に何も入れないでください。
常にDispose
を呼び出すべきかどうかに関するあなたの質問は、白熱した議論です。 .NETコミュニティの尊敬される個人からの興味深い視点については、 this ブログを参照してください。
個人的には、Dispose
の呼び出しは必須ではないというJeffrey Richterの立場は信じられないほど弱いと思います。彼は自分の意見を正当化するために2つの例を挙げています。
最初の例では、主流のシナリオでは、Windows FormsコントロールでDispose
を呼び出すことは退屈で不要であると述べています。ただし、主流のシナリオでは、Dispose
が実際にコントロールコンテナーによって自動的に呼び出されることに言及していません。
2番目の例では、開発者がIAsyncResult.WaitHandle
は、プロパティが待機ハンドルを遅延初期化することを認識せずに積極的に破棄し、不要なパフォーマンスの低下を招く必要があります。ただし、この例の問題は、IAsyncResult
自体がIDisposable
オブジェクトを処理するためにMicrosoftが公開しているガイドラインに準拠していないことです。つまり、クラスがIDisposable
型への参照を保持している場合、クラス自体はIDisposable
を実装する必要があります。 IAsyncResult
がその規則に従った場合、独自のDispose
メソッドが、その構成要素のどれを破棄する必要があるかを決定できます。
だから誰かがより説得力のある議論をしない限り、私は「常に廃棄」と呼ばれるキャンプに留まり、ほとんどがデザインの悪い選択から生じるいくつかのフリンジケースがあるだろうということを理解しています。
本当に簡単です。回答済みであることは知っていますが、もう一度試してみますが、可能な限りシンプルにしようとします。
通常、デストラクタは使用しないでください。 .netが実行したいだけです。ガベージコレクションサイクルの後にのみ実行されます。アプリケーションのライフサイクル中に実際に実行されることはありません。このため、実行する必要のあるデストラクタにコードを配置しないでください。また、実行時に存在するクラス内の既存のオブジェクトに依存することはできません(デストラクタの実行順序が保証されていないため、既にクリーンアップされている場合があります)。
IDisposibleは、クリーンアップが必要なリソース(ファイルとグラフィックスハンドルなど)を作成するオブジェクトがある場合は常に使用する必要があります。実際、デストラクタに入れるものはすべて、上記の理由によりIDisposableにする必要があると多くの人が主張しています。
ほとんどのクラスは、ファイナライザが実行されるときにdisposeを呼び出しますが、これは単に安全なガードとして存在するため、決して依存しないでください。完了したら、IDisposableを実装するものはすべて明示的に破棄する必要があります。 IDisposableを実装する場合は、ファイナライザーでdisposeを呼び出す必要があります。例については、 http://msdn.Microsoft.com/en-us/library/system.idisposable.aspx を参照してください。
ここに、IDisposable、GC、および廃棄物を取り巻くミストの一部をきれいにする別の素晴らしい記事があります。