26

USING ブロックでラップする必要がある場合とラップしない場合を知りたいです。

私が理解していることから、コンパイラはそれを try/finally に変換し、finally はオブジェクトで Dispose() を呼び出します。

私は常にデータベース接続とファイル アクセスの周りで USING を使用していますが、100% 理解しているというよりも、習慣から外れています。リソースを制御する Dispose() オブジェクトを明示的に (または使用して) 使用する必要があることはわかっています。これにより、CLR が気に入ったときにいつでも解放されるのではなく、即座に解放されるようになります。

IDisposables は、範囲外になったときに破棄されませんか?

オブジェクトが Dispose を使用して自分自身を整理する場合にのみ、USING を使用する必要がありますか?

ありがとう

編集: USING キーワードに関する他の投稿がいくつかあることは知っていますが、CLR に関する回答と、内部で何が起こっているのかについてもっと興味があります。

アンドリュー

4

3 に答える 3

22

いいえ、IDisposable対象外のアイテムは廃棄されません。IDisposable決定論的なクリーンアップが必要なのはまさにこの理由です。

それらは最終的にガベージコレクションを取得し、ファイナライザーがある場合は (おそらく) 呼び出されますが、それは将来的には長い時間になる可能性があります (接続プールなどには適していません)。ガベージ コレクションはメモリ プレッシャに依存します。余分なメモリが必要ない場合は、GC サイクルを実行する必要はありません。

興味深いことに(おそらく)、「使用」が面倒な場合があります。問題のあるクラスが例外をスローするDispose()場合があります。WCFはこれの違反者です。このトピックについては (簡単な回避策とともに)こちら で説明しました。

基本的に、クラスが を実装IDisposableしていて、インスタンスを所有している場合 (つまり、作成したものなど)、それが確実に破棄されるようにするのはあなたの仕事です。それは「使用する」ことを意味する場合もあれば、責任を負う別のコードに渡すことを意味する場合もあります。

私は実際に次のタイプのデバッグ コードを見てきました。

#if DEBUG
    ~Foo() {
        // complain loudly that smoebody forgot to dispose...
    }
#endif

(どこにDispose電話するかGC.SuppressFinalize

于 2008-11-25T12:37:30.617 に答える
5

「IDisposables は、範囲外になったときに破棄されませんか?」

いいえ。 IDisposable オブジェクトがfinalizableである場合、これは同じではありませんが、ガベージ コレクション時にファイナライズされます。

それはすぐかもしれませんし、ほとんどないかもしれません。

Jeff Richter の C#/CLR の本は、このすべてについて非常に優れており、Framework Design Guidelines の本も役に立ちます。

オブジェクトが Dispose を使用して自分自身を整理する場合にのみ、USING を使用する必要がありますか?

オブジェクトが IDisposable を実装している場合にのみ、'using' を使用できます。それ以外のことをしようとすると、コンパイラは反対します。

于 2008-11-25T12:38:43.703 に答える
2

他の回答に追加するにはusing、オブジェクトがマネージド メモリ以外のリソースを保持している場合は常に (または明示的な Dispose を使用する必要があります)。例としては、ファイル、ソケット、データベース接続、または GDI 描画ハンドルなどがあります。

ガベージ コレクターは最終的にこれらのオブジェクトをファイナライズしますが、それは将来の不特定の時点でのみです。タイムリーに行われるとは限りません。その間にそのリソースが不足している可能性があります。

于 2008-11-25T12:55:01.580 に答える