EventHandlerは、クラスの定義でのみ=演算子を許可することをどのように知っていますか?
-
03-07-2019 - |
質問
質問から始めて、質問を入力して答えを見つけましたが、削除する代わりに、A)確認を取得し、B)他の人を助けることが役立つと思いました。
イベントがあり、アプリケーションの複数の場所でリスナーを追加する場合、すべてのリスナーを一度に削除する最良の方法は何ですか?たとえば、...
myPage.OnPageOpened += OpenPage;
以降のコードで...
myPage.OnPageOpened -= OpenPage;
しかし、未知のサードパーティサブスクライバーがあり、すべてをクリアしてゼロから開始する魔法のリセットボタンを押したい場合はどうなりますか?
演算子のオーバーロードはパブリックであるため、EventHandlerに対してどこでも+ =および-=演算子を使用できます。 =オーバーロード演算子はプライベートです。定義クラスでのみ呼び出すことができます。
したがって、定義クラスでは、これを使用してEventHandlerをクリアできます。
OnPageOpened = null;
そしてその機能を公開するために、私は...
public void ClearPageOpenedEvents() {
OnPageOpened = null;
}
それは正しいですか?
解決
はい、あなたは正しいです。この理由は、次のように、コンパイラがカバーの下に private
delegate
オブジェクトを作成するためです:
private EventHandler pageOpened;
public EventHandler PageOpened
{
add { pageOpened += value; }
remove { pageOpened -= value; }
}
クラスの内部には、プライベート delegate
インスタンスへの参照があるため、割り当てを行うことができます。必要な機能である場合、ターゲットをクリアするメソッドを必ず公開する必要があります。 デリゲート
自体を公開したくない場合。
他のヒント
それはそれを行う方法ですが、クラス外の何かが、クラスがすべてのイベントリスナーをドロップする必要があることをどのように認識するのでしょうか?コードを拡張/使用する誰かがそのイベントを継続的に期待している場合はどうなりますか?
イベントに対して割り当て演算子を使用できます。これが、イベントの追加と削除の仕組みです。 Reflectorを使用すると、C#でのイベントの実行方法に多くの光が当てられます。
の単純なクラスを指定
public class MyClass
{
public event EventHandler MyEvent;
}
コンパイル時に次のコードが生成されます
public class MyClass
{
private EventHandler MyEvent;
public event EventHandler MyEvent;
}
したがって、 MyEvent
を参照するときは、プライベートデリゲート変数 MyEvent
を参照します。 + =
および-=
演算子は" special"です。 (これらは演算子ではないため)、イベントに対して作成された add
および remove
メソッドを呼び出すように変更されます(これらは割り当て演算子自体を使用します)。
[MethodImpl(MethodImplOptions.Synchronized)]
public void add_MyEvent(EventHandler value)
{
this.MyEvent = (EventHandler) Delegate.Combine(this.MyEvent, value);
}
[MethodImpl(MethodImplOptions.Synchronized)]
public void remove_MyEvent(EventHandler value)
{
this.MyEvent = (EventHandler) Delegate.Remove(this.MyEvent, value);
}