管理されていないリソースの割り当てを解除するために使用されることは理解していますが、Dispose
実際にいつ呼び出されるかについては混乱しています。ブロックの最後で呼び出されることは知っていusing
ますが、オブジェクトがガベージコレクションされたときにも呼び出されますか?
4 に答える
IDisposable を正しく実装する場合は、オブジェクトで Dispose() を呼び出すファイナライザーも含める必要があります。
これを行うと、GC によって呼び出されます。ただし、これらのオブジェクトを常に自分で破棄することをお勧めします。
Dispose の呼び出しをファイナライザーに依存することの最大の問題は、制御していない別のスレッドで発生することです。これは、特定の状況で厄介な結果をもたらす可能性があります。たとえば、GC スレッドで発生している例外を引き起こしたり、破棄されたフィールドをチェックしたりします。これは、Dispose() メソッドに GC.SuppressFinalize(this) を含めることが重要である理由の一部でもあります。オブジェクトが破棄されると、再破棄したくありません。
Dispose はいくつかの場所で呼び出されます。
- using ブロックの最後。
- 明示的に呼び出された場合 (たとえば、try{} finally{} で)。
リソースをより適切に管理するために、リソースを使い終わったら自分で呼び出すことをお勧めします。
編集:私は間違っていました。Dispose は、ガベージ コレクション中には呼び出されません。この記事を参照してください。
Dispose() は Using ブロックの最後で呼び出されるため、オブジェクトがスコープ外になったときに発生する Dispose アクション (db 接続のクローズなど) を期待できます。そのような単純な。
更新: Dispose の呼び出しには、 アンマネージリソースに固有のものはありません(ただし、これは一般的な使用方法です)。
更新 2 : Reed Copsey が開始したスレッドには、IDisposable を理解するのに役立つちょっとした議論があります。詳しく知りたい人 はこちらの記事がおすすめです。
簡単に言うと、IDisposable クラスを使用すると、Dispose() メソッドを介してリソース (通常はアンマネージ リソースまたはデータベース接続) の割り当て解除を明示的に処理できます。Dispose メソッドが実際に呼び出されるように、IDisposable クラス インスタンスは "Using" ブロック内に作成する必要があります。これを行わなかった場合 (または "finally" ブロックなどで明示的に呼び出した場合)、Dispose メソッドは呼び出されず、クリーンアップしたいオブジェクトが孤立してしまいます。すべての場合において、Disposable クラスを Using ブロックに配置します。
別の方法として、Finalizer (クラス Destructor) でリソースのクリーンアップを処理できます。これは、クラスが GC されたときに自動的に呼び出されます。このアプローチの欠点は、オブジェクトがいつクリーンアップされるかを明示的に制御できないことと、対処すべきスレッドの問題がいくつかあることです。したがって、たとえば、デストラクタの問題は、非同期で別のスレッドで呼び出されるため、デバッグが非常に困難です。唯一の利点は、Dispose のように Destructor を呼び出すことを覚えておく必要がないことです。もちろん、常に Using ブロックを使用している場合、これは問題ではありません。
注: 私 ktrauberman、Reed、および Pontus は、以下で説明するポイントを回避する方法について、いくつかの良い点を指摘しています。これが私がしていることですが、これが物事を行う唯一の方法であると主張することはできません. 実際、マイクロソフトは場合によってはファイナライザーから Dispose() を呼び出すことを推奨しています。ただし、Destructors と Dispose() を混在させるときは注意してくださいという Reed のアドバイスに従うことが重要である理由を説明するために、ここでの説明は省略します。
リードの答えに同意できないのは、ファイナライザー内で Dispose() を呼び出して IDisposable クラスを実装する必要があるという主張です。これは、2 つの異なる構造を混同するだけであり、問題を引き起こす可能性があります。たとえば、Using ブロックで IDisposable クラス インスタンスを作成し、デストラクタで Dispose() を呼び出すと、それが 2 回呼び出され、クラッシュが発生する可能性があり、デバッグが困難になる可能性があります (これも、タイミングを制御しません)。 GC)。(サイドノート: これはデストラクタ全般に当てはまります - 特定の状況では複数回呼び出される可能性があります!)
いいえ、オブジェクトがガベージ コレクションされたときに呼び出されません。その動作が必要な場合は、デストラクタ (ファイナライザ) とDispose()
そこからの呼び出しを使用できます。
あなたが言うように、それは自動的に呼び出され、using
ブロックの終わりです。