2011-07-20 3 views
11

MSDN's example pattern廃棄()メソッドを実装するためにはヌルに配置された管理対象リソース(_resource = null)への参照を設定示すが、if (disposing)ブロックの外側そう:MSDN Dispose()の例で誤りがありますか? (nullに管理対象の参照を設定する場合)

protected virtual void Dispose(bool disposing) 
{ 
    // If you need thread safety, use a lock around these 
    // operations, as well as in your methods that use the resource. 
    if (!_disposed) 
    { 
     if (disposing) { 
      if (_resource != null) 
       _resource.Dispose(); 
       Console.WriteLine("Object disposed."); 
     } 

     // Indicate that the instance has been disposed. 
     _resource = null; 
     _disposed = true; 
    } 
} 

Shouldn '_resource = nullはこのコードブロックの中に置かれますか? Dispose(false)への電話が行われた場合、_resourceはヌルになり、その後処分できなくなります。 ??

もちろん、Dispose(false)は、ファイナライズ中にランタイムによって(実際には)呼び出されるだけです。しかし、_resourceが以前に処分されていなかった場合、オブジェクト(_resourceのメンバーフィールドを含む)がガベージコレクションされる直前に、この時点でnullに設定する必要はありますか?

ずっと読みになった後、それがnullへの参照が必要でない設定に表示されますが、「重い」メンバーのために良いアイデアかもしれ:


[元の質問の終わり]

フォローアップあなたが含まれているクラス(処分されているクラス)がすぐにガベージコレクションされないかもしれないと信じる理由がある場合、オブジェクト。

オブジェクトの廃棄は、コードを消費してオブジェクトが「解放」されたことを保証していないことを理解してください。廃棄されたオブジェクトは、さまざまな目的のために、または間違って(コレクションなどで)保持されることがあります。コレクションのオブジェクトを使用して破棄するアプリケーションを想像することはできますが、後で削除を実行して最終状態を記録するためのコレクションにコレクションを保管しておいてください...

結論:

  1. 「重い」メンバーオブジェクトへの参照を設定するには、解放それらに配置されたオブジェクトが解放されていない場合でも、ガベージコレクションの をゼロにします。
  2. すべてのオブジェクトの参照をクリアするのは大変です。
  3. したがって、_resource = nullステートメント(元の質問)の配置は、次の2つの理由から重要ではありません。(A)これを使用することは、上記を読んだ後に考えることに過ぎません。 (B)MSDNの例では、Dispose(true)Dispose(false)の両方で実行されますが、後者はオブジェクトがファイナライズされていて、とにかくガベージコレクションが行われるだけです。

このように、私の好みは、最も内側のifブロック内_resource = nullを置くことになります。これは、一緒にすべての_resourceコードを保持します

if (disposing) { 
    if (_resource != null) { 
     _resource.Dispose(); 
     _resource = null; 
    } 
} 

。さらなる考え、誰ですか?

もっと読み:

+1

ほとんど目的を果たしていませんが、ほとんど害はありません...実際には、私は 'Console'への書き込みと、' Console'への書き込みは、すでに処分されていても、それを処分しないでください( 'if'に欠けている中カッコを見てください)。 –

+0

ハハ! 'Console.Writeline()'はサンプルコードです。 Trace.Writeline()あなたはよかったですか?また、不足しているブレースはありません。これは 'if'行の最後にあります(StyleCopに準拠していません)。 –

+0

再度見てください。それは "Object disposed"と書いています。 '_resource'がnullだったとしても' .Dispose() 'は呼び出されませんでした。私は*最も内側の* ifを意味します。 –

答えて

6

nullに設定すると、ヒープ内の位置への参照またはポインタが削除されます。これにより、GCはあまり推測することなく参照を持たないものをすべて通過して削除することができます。 _resourceは、参照をクリーンアップする必要がある内部使用オブジェクトであるため、ソケットの内部を閉じるか、そのソケットやその他の永続リソースを閉じる/取り消すことができます。それが破棄されたら、nullに設定してすべての参照を削除してください(すべての参照を削除する必要があります)。私の答えの後半はいくつかのことを繰り返す例ですが、あなたがそのアイデアを得ることを願っています。

nullに2回設定することは効果がないため大したことではありません。廃棄は、リソースをクリーンアップするときには真実でなければならず、とにかくガベージコレクションが行われると(あなたの言ったように)それが偽であるだけです。

+0

おそらく、それはどこに行くのに大きな違いはありませんか? '_resource = null'を' _resource.Dispose() 'の直後に置くことによって、これらの関連する項目が(' = null'で多くの項目が配置されていると仮定して)一箇所にあるので、コードを読みやすく/維持しやすくなります。 –

+0

また、 '_resource'は管理されたリソースです(おそらくソケットではありません)。 MSDNパターンは 'if(disposing)'ブロックの中に管理対象オブジェクトの廃棄のみを置きます。私は '_resource = null'が' _resource.Dispose() 'の直下にない理由があるかどうかを理解しようとしています。 –

+0

ソケットは、コード内で、何らかの理由で(WebServiceコネクタまたはHttpListenerと同じように)常時開かれているものとして管理することができます。これは、適切に閉じなければならないか、メモリリークやその他の種類のリソースリークを引き起こす可能性があります。使用されなくなった)。ほとんどのアイテムは管理する必要がないので、単にnullに設定するだけで、GCはそのトリップの1つでそれらを取得します。 –

関連する問題