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


183

次のコードがある場合:

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

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

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

11
この質問に興味がある読者には、ガベージコレクションの発生を防止しない軽量イベント/弱いイベントパターンに慣れる価値があるかもしれないことを暫定的に提案します。このトピックに適したSOブートストラップは、stackoverflow.com
questions / 185931 /…

20
後世への注意:参照をnullに設定すると、参照のスコープが1行拡張されてガベージコレクターが遅延します。.NETはVB6ではありません。
ジョンサンダース

回答:


207

「pClassはガベージコレクションされますか」という特定の質問の場合:イベントサブスクリプションは、(発行者としての)pClassのコレクションに影響を与えません。

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

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

これは一方向であることに注意してください。つまり、私たちが持っている場合:

publisher.SomeEvent += target.SomeHandler;

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

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

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


6
さて、質問が「pClassはガベージコレクションされますか」の場合、「...かどうかによって異なります」という答えは実際には正しくありません。マルク自身がさらに指摘するように、それは何にも依存しません。
Tor Haugen、

@トール-十分公正-明確にします
マークグラベル

イベントサブスクリプションデリゲートは一方向のみを指しますが、サブスクライバーは、イベントの完了時にイベントのサブスクライブを解除するつもりがある場合、パブリッシャーへの何らかの参照を必要とします。それはWeakReferenceかもしれませんし、いくつかのケースではそれは良い考えかもしれませんが、多くの場合、それは強力なものになるでしょう。
スーパーキャット2012

質問の残り半分(質問されなかった)にも対応しているため、すばらしい回答です。パブリッシャーサブスクライバーの GC を停止します
Bob Sammers 2017年

はい、そして@BobSammersが言ったように、フォーム/ウィンドウなどの短寿命インスタンスが、たとえばデータを提供するシングルトンのような長寿命サービスにサブスクライブしている場合、本当に問題になる可能性があります。シングルトンは参照を保持しますであり、オブジェクトはアンロードされたと思ってもメモリに保持されます!したがって、イベントを使用するときは十分に注意してください。私たちは大きなソフトウェアのイベントを悪用しており、その後の解決は非常に困難です。
Elo

9

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

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


8

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

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


0

pClassごみ収集されます。ただし、上記のコードスニペットが別のクラス内にある場合、に設定pClassしないと、そのクラスのインスタンスはクリアされない可能性がありますnull

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.