いつデストラクタではなくクラスにIDisposeを実装しますか?この記事を読みましたが、まだ要点がありません。
私の想定では、IDisposeをオブジェクトに実装すると、ガベージコレクターがIDisposeを実行するのを待つのではなく、明示的に「破棄」できるということです。これは正しいです?
つまり、常にオブジェクトに対してDisposeを明示的に呼び出す必要がありますか?これのいくつかの一般的な例は何ですか?
いつデストラクタではなくクラスにIDisposeを実装しますか?この記事を読みましたが、まだ要点がありません。
私の想定では、IDisposeをオブジェクトに実装すると、ガベージコレクターがIDisposeを実行するのを待つのではなく、明示的に「破棄」できるということです。これは正しいです?
つまり、常にオブジェクトに対してDisposeを明示的に呼び出す必要がありますか?これのいくつかの一般的な例は何ですか?
回答:
ファイナライザ(デストラクタとも呼ばれます)はガベージコレクション(GC)の一部です。GCは主にメモリプレッシャーの結果として発生するため(つまり、より多くのスペースが必要になるため)、いつ発生するか(発生しても)は不確定です。ファイナライザーは通常、管理されていないリソースのクリーンアップにのみ使用されます。管理されたリソースには独自の収集/破棄があります。
したがって、オブジェクトIDisposable
を確定的にクリーンアップするために使用されます。オブジェクトのメモリ(まだGCに属している)は収集しませんが、ファイルやデータベース接続などを閉じるために使用されます。
これに関するこれまでのトピックはたくさんあります:
最後に、IDisposable
オブジェクトがファイナライザを持つことも珍しくないことに注意してください。この場合、Dispose()
通常はを呼び出しますGC.SuppressFinalize(this)
。これは、GCがファイナライザを実行しないことを意味します。メモリを捨てるだけです(はるかに安価)。Dispose()
オブジェクトを忘れた場合でもファイナライザーは実行されます。
このFinalize()
メソッドの役割は、.NETオブジェクトがガベージコレクション時にアンマネージリソースを確実にクリーンアップできるようにすることです。ただし、データベース接続やファイルハンドラーなどのオブジェクトは、ガベージコレクションに依存するのではなく、できるだけ早く解放する必要があります。そのためには、IDisposable
インターフェースを実装し、Dispose()
メソッドでリソースを解放する必要があります。
このインターフェイスの主な用途は、アンマネージリソースを解放することです。ガベージコレクターは、そのオブジェクトが使用されなくなったときに、管理オブジェクトに割り当てられたメモリを自動的に解放します。ただし、ガベージコレクションがいつ発生するかを予測することはできません。さらに、ガベージコレクターは 、ウィンドウハンドルや開いているファイルやストリームなどのアンマネージリソースを認識していません。
このインターフェイスのDisposeメソッドを使用 して、ガベージコレクターと共にアンマネージリソースを明示的に解放します。オブジェクトの コンシューマは、オブジェクトが不要になったときにこのメソッドを呼び出すことができます。
C#デストラクタにあるべき唯一のものは次の行です。
Dispose(False);
それでおしまい。そのメソッドに他のものはありません。
常に電話をかけるべきかどうかについてのあなたの質問Dispose
は通常白熱した議論です。.NETコミュニティで尊敬される個人からの興味深い見解については、このブログを参照してください。
個人Dispose
的には、呼び出しは必須ではないというジェフリー・リヒターの立場は信じられないほど弱いと思います。彼は自分の意見を正当化するために2つの例を挙げています。
最初の例ではDispose
、主流のシナリオではWindowsフォームコントロールを呼び出すのは面倒で不要です。ただし、Dispose
主流のシナリオでは、実際にはコントロールコンテナーによって自動的に呼び出されることについては触れていません。
2番目の例ではIAsyncResult.WaitHandle
、プロパティが待機ハンドルを遅延初期化することを認識せずに、インスタンスfrom を積極的に破棄する必要があると開発者が誤って想定し、不要なパフォーマンスペナルティが発生する可能性があると述べています。しかし、この例の問題は、IAsyncResult
それ自体がIDisposable
オブジェクトを処理するためのMicrosoft独自の公開ガイドラインに準拠していないことです。つまり、クラスがIDisposable
型への参照を保持している場合、クラス自体が実装する必要がありますIDisposable
。IAsyncResult
そのルールに従えば、独自のDispose
方法で、構成メンバーのどれを処分する必要があるかを決定できます。
したがって、誰かがより説得力のある議論をしない限り、私は「常にDisposeを呼び出す」キャンプにとどまり、主に不適切な設計の選択から生じるいくつかの周辺のケースがあることを理解します。
とてもシンプルです。回答済みであることは承知していますが、もう一度やり直しますが、できる限りシンプルにするよう努めます。
デストラクタは通常使用しないでください。.netは実行したいだけです。ガベージコレクトインサイクルの後でのみ実行されます。アプリケーションのライフサイクル中に実際に実行されることはありません。このため、「実行する必要がある」デストラクタにコードを配置しないでください。また、実行時にクラス内の既存のオブジェクトに依存することもできません(デストラクタが実行される順序が保証されていないため、既にクリーンアップされている可能性があります)。
IDisposibleは、クリーンアップが必要なリソース(つまり、ファイルおよびグラフィックスハンドル)を作成するオブジェクトがある場合は常に使用する必要があります。実際、多くの人は、上記の理由により、デストラクタに入れるものはすべてIDisposableにする必要があると主張しています。
ほとんどのクラスは、ファイナライザが実行されるときにdisposeを呼び出しますが、これは単に安全策として存在するものであり、決して信頼してはなりません。使い終わったら、IDisposableを実装するものはすべて明示的に破棄する必要があります。IDisposableを実装する場合は、ファイナライザでdisposeを呼び出す必要があります。例については、http://msdn.microsoft.com/en-us/library/system.idisposable.aspxを参照してください。
これは、IDisposable、GCを取り巻く霧の一部を取り除き、処分する別のすばらしい記事です。
using
構成を使用して簡単に行うことができます。