2009-05-29 6 views
5

私は次のような場合:それはデリゲートをくしゃみているためガベージコレクタはイベントを購読しているオブジェクトをクリアしますか?

public class Test 
{ 
    public static void Main() 
    { 
     List<Person> persons = new List<Person> { new Person() }; 

     persons[0].Sneezing += new EventHandler(Person_Sneezing); 

     persons = null; 
    } 

    public static void Person_Sneezing(object sender, EventArgs e) 
    { 
     (sender as Person).CoverFace(); 
    } 
} 

人にあった人は、[0]、まだメモリ内に存在していますがPerson_Sneezingメソッドへの参照を持っているか、それがGCによって収集されますでしょうか?

答えて

8

これはGCによって収集されます。

  1. 値強いGCに根ざした値が
  2. コーナーケースや2私はハンドル
  3. スタックに...オブジェクトが、直接または間接的にで参照する必要があり、メモリに保持されるために現時点では考えていない

これは人物[0]のオブジェクトには当てはまりません。だからそれは集められるでしょう。

これはもちろん、Person()のコンストラクタがThreadLocalStorageに自分自身を追加するような面白いことをしていないことを前提としています。

1

あなたが既に持っている答えに加えて、より現実的な例に注意する必要があります。

プログラムが実行されている間存続するメインウィンドウがあり、そのメソッドをメインウィンドウのイベントに参加させる「短命」オブジェクトを頻繁に作成する場合は、それらのイベントからオブジェクトを削除する必要がありますそうでなければそれらのオブジェクトはまったく「短命」にならないからです。メインウィンドウの長さ、つまりユーザーがアプリケーションを閉じるまで、それらは生き残ります。有効な結果はメモリリークと同等です。

短寿命オブジェクトのクラスをIDisposableに実装すると、Disposeのイベントから除外でき、オブジェクトを破棄するときにdisposeを呼び出すことができます。

6

あなたは途中です。これは他の方法でだった場合、これはメモリリークになります。親クラスが上のメソッドへの参照を持っているので

public class Test 
{ 
    public void HookupStuff() 
    { 
     List<Person> persons = new List<Person> { new Person() }; 

     this.EventHappened += new EventHandler(persons[0].SomeMethod); 
     // persons[0].Sneezing += new EventHandler(Person_Sneezing); 

     persons = null; 
    } 
} 

persons[0]は、あなたがpersonsをゼロにもかかわらず、周りに固執する:それはこのように見えた場合、ある

+0

あなたはそれをリークと呼べますか?もしテストが行​​くなら人もそうする[0]。 –

+0

もちろん、すべてが消えてしまう*最悪の場合、アプリケーションが終了するとすべて消えてしまう!あなたがそれがなくなると思うときに消えないときは、それを漏れと呼ぶだろう。 – mquander

+0

(また、人物[0]への別の参照をしなかった場合は、それを元に戻すことが難しいため、基本的には無駄に漏れてしまいます。) – mquander

関連する問題