そのパターンはあなたが期待するものではないと思います。メモリ リークを防ぐために、イベントが現在のオブジェクトへの参照を保持しないようにしようとしていますか? ラムダ式は、this
評価するためにの値をキャプチャするためProcessEvent
(インスタンス メソッドであると仮定ProcessEvent
)、リークは引き続き発生します。このコードは、実行するのと同じSomeEvent += (sender, e) => ProcessEvent();
です。
あなたはもっとこのようなことをしようとしているかもしれません(これもあなたが望むものではありません):
var reference = new WeakReference((Action)ProcessEvent);
SomeEvent += (sender, e) => ((Action)reference.Target)();
これで、ラムダ式は WeakReference をキャプチャするため、 への強い参照はありませんthis
。残念ながら、ProcessEvent から作成されたデリゲートを参照しているものは他にないため、デリゲートthis
がまだ生きている場合でも次の GC で削除されます。(これは、Target が null であることもチェックしません)。
次のようなことを試すことができます:
public EventHandler MakeWeakHandler(Action action, Action<EventHandler> remove)
{
var reference = new WeakReference(action.Target);
var method = action.Method;
EventHandler handler = null;
handler = delegate(object sender, EventArgs e)
{
var target = reference.Target;
if (target != null)
{
method.Invoke(target, null);
}
else
{
remove(handler);
}
};
return handler;
}
そして、次のように使用します。
SomeEvent += MakeWeakHandler(ProcessEvent, h => SomeEvent -= h);
これにより、ProcessEvent のレシーバーへの弱い参照が維持され、収集後にイベント ハンドラーがイベントから自動的に削除されます。これにより、イベントが定期的に発生する限り、メモリ リークが防止されます。