web-dev-qa-db-ja.com

イベントハンドラーの登録を解除しないのは悪いことですか?

少数のイベントハンドラーしか登録されていないアプリケーションがある場合(そして、イベントを使用するオブジェクトは、アプリケーションが閉じられるまで破棄されません)、それらのハンドラーの登録を解除することを本当に心配する必要がありますか?私が見ることができた唯一の正当な理由は、必要のないイベントが発生している場合(つまり、1つのイベントに複数のハンドラーが登録されている場合)に少し余分なオーバーヘッドが発生する可能性があることです。他に正当な理由はありますか?イベントの登録を解除しなかったために大きな問題が発生した人はいますか?

64
SwDevMan81

Aがイベントを公開し、Bがイベント(ハンドラー)をサブスクライブしている場合、Aがライブになる場合は、サブスクライブを解除しないことが問題になります。 Bよりはるかに長い。基本的に、イベントサブスクリプションは、ABを引き続き認識できることを意味するため、ガベージコレクションが防止され、忘れた場合でもイベントが発生します(おそらくDisposed() it)。

たとえば、これはAが静的イベントであり、Bが停止した後しばらくの間アプリが実行される場合に問題になります...しかし、BA、したがってBはガベージコレクションされません。

注意することが重要です、人は次のことを尋ねるかもしれません:

bがAよりもはるかに長生きする場合、BはAがガベージコレクションされないようにしますか?

そして、その答えは「いいえ」です。 Bは、イベントを通じてAを参照していません。 Aは通常通り回収されます

82
Marc Gravell

多くの人々は、発行者が購読者よりも長生きする場合にのみ、イベントの購読を解除することが重要であると考えているようです。私はそのアプローチが嫌いです。パブリッシャーから切り離されないイベントサブスクライバーは、パブリッシャーとサブスクライバーの外部のエンティティの動作に厄介な依存関係を作成します。パブリッシャーへの参照が予想よりも長く保持されている場合、サブスクライバーが参照を保持しているオブジェクトとともに、サブスクライバーが存続します。大量の放棄されたオブジェクトがイベントハンドラーによって相互接続されているが、それらのいずれにもライブ参照が存在しない場合、すべてのオブジェクトがガベージコレクターによってスイープされる可能性があります。ただし、誰かが予期せずにオブジェクトの1つへの参照を保持していると、それらのいずれかがガベージコレクションされなくなる可能性があります。

私見ですが、イベントハンドラーを破棄してすべてがクリーンアップされることを期待するよりも、積極的にイベントハンドラーを削除する方がはるかに優れています。出版社への予期しない参照が存在しないことが確実でない限り、そのようなアプローチは「ほとんど」機能する可能性がありますが、時折メモリリークを引き起こします。

15
supercat