web-dev-qa-db-ja.com

イベントハンドラは、ガベージコレクションの発生を停止しますか?

次のコードがある場合:

MyClass pClass = new MyClass();
pClass.MyEvent += MyFunction;
pClass = null;

PClassはガベージコレクションされますか?それとも、イベントが発生するたびにイベントを起動し続けますか?ガベージコレクションを許可するには、次のことを行う必要がありますか?

MyClass pClass = new MyClass();
pClass.MyEvent += MyFunction;
pClass.MyEvent -= MyFunction;
pClass = null;
176
Mark Ingram

「pClassをガベージコレクションする」という特定の質問の場合:イベントサブスクリプションは(パブリッシャーとしての)pClassのコレクションには影響しません。

一般的なGC(特にターゲット)の場合:MyFunctionが静的かインスタンスベースかによって異なります。

インスタンスメソッドへのデリゲート(イベントサブスクリプションなど)には、インスタンスへの参照が含まれます。はい、イベントサブスクリプションはGCを防ぎます。ただし、イベントを発行するオブジェクト(上記のpClass)が収集の対象になるとすぐに、これは問題ではなくなります。

これは一方向であることに注意してください。つまり、次の場合:

publisher.SomeEvent += target.SomeHandler;

「パブリッシャー」は「ターゲット」を存続させますが、「ターゲット」は「パブリッシャー」を存続させません。

そのため、pClassがとにかく収集される場合、リスナーをサブスクライブ解除する必要はありません。ただし、pClassが長期間(MyFunctionのインスタンスよりも長い)存続している場合、pClassはそのインスタンスを存続させることができるため、ターゲットを収集する場合は、サブスクライブを解除する必要がありますwould.

ただし、静的イベントは、このため、インスタンスベースのハンドラーと併用すると非常に危険です。

196
Marc Gravell

はい、pClassはガベージコレクションされます。イベントサブスクリプションは、pClassへの参照が存在することを意味しません。

そのため、pClassをガベージコレクションするためにハンドラを切り離す必要はありません。

7
Tor Haugen

メモリの一部が参照されなくなった瞬間に、ガベージコレクションの候補になります。クラスのインスタンスが範囲外になると、プログラムから参照されなくなります。使用されなくなったため、安全に収集できます。

何かが収集されるかどうかわからない場合は、次の質問を自問してください:まだ参照が存在しますか?イベントハンドラーは、オブジェクトインスタンスによって参照されますが、その逆ではありません。

7
lvaneenoo

pClassはガベージコレクションされます。ただし、上記のコードスニペットが別のクラス内にある場合、pClassnullに設定しないと、そのクラスのインスタンスがクリアされない場合があります。

0
Arav