WeakReference
私は「TheC#Language」、第4版を読んでいます、それは話しWeak Event Pattern
ます:
CHRISTIAN NAGEL:メモリリークは、イベントの誤った使用に起因することがよくあります。クライアントオブジェクトがイベントにアタッチされているが、イベントから切り離されておらず、クライアントオブジェクトへの参照が使用されなくなった場合でも、パブリッシャーによる参照が残っているため、クライアントオブジェクトをガベージコレクターが再利用することはできません。これは、(1)クライアントオブジェクトが使用されなくなったときにイベントをデタッチする、(2)デリゲートを保持するクラスを使用する、
add
およびremove
アクセサーのカスタム実装、または(3) IWeakEventListenerでWPFによって使用されるイベントによって回避できます。インターフェース。WeakReference
Weak Event pattern
ここで疑問があります。オプション「(2)WeakReference
」は、「オプション(1)イベントの明示的なデタッチ」と比較して、まったく便利ではありません。これは、を使用すると、との両方をWeakReference
明示的に呼び出す必要があるためです。add
remove
そうしないと、イベントハンドラーのオブジェクトの1つがnullに割り当てられた場合でも、「孤立した」オブジェクトはイベントに応答します。これにより、予期しない動作が発生します。
注:WeakReference
イベントハンドラーのオブジェクトがイベントパブリッシャーオブジェクトの影響を受けないようにする方法でのみ、ガベージコレクションを支援します。WeakReference
イベントハンドラオブジェクトにガベージコレクションを強制しません。
同様の問題は、弱いイベントパターンにも当てはまります。
これは少し抽象的かもしれません。例として、Josh Smithのメディエーターパターン(http://joshsmithonwpf.wordpress.com/2009/04/06/a-mediator-prototype-for-wpf-apps/)を取り上げます。
public class Mediator //...
{
public void Register(object message, Action<object> callback)
{
// notice: Mediator has no Unregister method
}
public void NotifyColleagues(object message, object parameter)
{
// ...
}
}
public class ObjectA //...
{
public string ObjectAText
{
get { return _objectAText; }
set
{
//...
_mediator.NotifyColleagues(MediatorMessages.ObjectASaidSomething, _objectAText);
}
}
}
public class ObjectB //...
{
//...
public ObjectB(Mediator mediator)
{
//...
_mediator.Register(
MediatorMessages.ObjectASaidSomething,
param =>
{
// handling event ObjectASaidSomething
});
}
}
私たちが持っている場合
ObjectA objectA = new ObjectA();
ObjectB objectB1st = new objectB();
objectA.ObjectAText = "John"; // objectB1st will respond to this event.
objectB1st = null; // due to delay of garbage collection, the object is actually still in memory
ObjectB objectB2nd = new objectB();
objectA.ObjectAText = "Jane"; // both objectB1st and objectB2nd will respond to this event!
最後の行は、?のために予期しない動作を引き起こしませんでしたWeakReference
か?
しかし、Mediator
クラスが「登録解除」メソッドを提供する場合(実際に私はそれを実装しました)、「オプション(2)WeakReference
」は「オプション(1)イベントを明示的にデタッチする」と違いはありません。(メディエーター自体は依然として有用なパターンであり、WPFまたはMVVMコンポーネントレイヤーの階層に侵入できます)