実現したいこと
C# イベントハンドラについての質問です。
イベントハンドラを登録する際、
FooInstance.FooEvent += FugaMethod();
のような書き方をすると思います。
上記は、イベントハンドラを追加している意味合いになると思いますが、
すでに登録されている場合、それを削除して新しく登録するような機能を求めています。
これは標準機能として存在しているのでしょうか?それとも、アクセサを明示的に実装するべきでしょうか?
もしそういった機能が標準で備わっているとしたら、自分では見つけられなかったのでドキュメントのリンクなどを貼っていただけると助かります。
補足情報(FW/ツールのバージョンなど)
Visual Studio 2022 C# 8.0
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答2件
0
ベストアンサー
すでに登録されている場合、それを削除して新しく登録するような機能を求めています。
不要となったデリゲートを -= で削除できます。
昔の Microsoft のチュートリアル(今はリンク切れ)に自分的に参考になったコードがあるので以下に貼っておきます。コメントは私が追加したものなので、信ぴょう性がイマイチかもしれないのでご注意を。
C#
1// イベントとは、オブジェクトでクライアントに有益な事象が発生したときに、クラスからクライ 2// アントへ通知する方法のこと。 3// 4// イベント使用の典型的な例は Windows フォームのコントロール。通常、インターフェイスのコ 5// ントロールを表すクラスには、ユーザーがコントロールに対して何らかの操作 (ボタンのクリッ 6// クなど) を行ったときに通知されるイベントが設定されている。 7// 8// イベントの宣言には、デリゲートを使用する。イベントが発生すると、クライアントによって 9// フックされたデリゲートが呼び出される。 10 11// 2015/2/7 以下のページを見つけたのでメモしておく: 12// 方法 : .NET Framework ガイドラインに準拠したイベントを発行する (C# プログラミング ガイド) 13// https://docs.microsoft.com/ja-jp/dotnet/csharp/programming-guide/events/how-to-publish-events-that-conform-to-net-framework-guidelines 14 15// 方法 : 派生クラスから基本クラス イベントを発生させる (C# プログラミング ガイド) 16// https://docs.microsoft.com/ja-jp/dotnet/csharp/programming-guide/events/how-to-raise-base-class-events-in-derived-classes 17 18using System; 19using System.Collections; 20 21namespace MyEventTest 22{ 23 // 宣言されていない場合は、最初にイベントのデリゲート型を宣言する必要がある。sender 24 // はイベントが発生したオブジェクトへの参照。e はイベントデータが格納されているオブ 25 // ジェクトへの参照。 26 // ライブラリの EventHandler を使う場合は、宣言済みらしく、この宣言は不用。 27 // 引数はライブラリの EventHandler と合わせているが、このサンプルでは使っていないの 28 // で、ChangeEventHandler(引数なし) として書き直しても同じ結果になる。 29 30 public delegate void ChangedEventHandler(object sender, EventArgs e); 31 32 public class ListWithChangedEvent : ArrayList 33 { 34 // イベントの宣言 35 // event キーワードに注意。 36 // クラスの外からはフィールドのように見える。ただし、アクセスには制限があり、実行で 37 // きるのは、以下の処理だけ。 38 // ・新しいデリゲートの結合 39 // ・(結合されている場合は)デリゲートの削除 40 // これらの処理には、+= および -= 演算子を使用する。下記の EventListener クラス参照 41 42 public event ChangedEventHandler Changed; 43 44 // イベントの起動 45 // デリゲートをイベントにフックしているクライアントがない場合、フィールドは null に 46 // なる。それ以外の場合は、イベント起動時に呼び出すデリゲートへの参照となる。このた 47 // め、一般にイベントが起動される場合はまずこのフィールドが null かどうかを調べ、そ 48 // の後イベントを呼び出す。 49 50 // イベントは、イベントを宣言したクラスの中からしか起動できない。イベントを起動する 51 // protected メソッドを作成しておき、このメソッドを呼び出すことによって、派生クラスが 52 // イベントを起動できる。さらに柔軟性を持たせるために、起動メソッドを virtual とし 53 // て宣言することも多くある。これにより、派生クラスは、そのメソッドをオーバーライド 54 // できる。 55 protected virtual void OnChanged(EventArgs e) 56 { 57 if (Changed != null) 58 Changed(this, e); 59 } 60 61 // リストへの追加、リストのクリア、リストの要素への代入の際にイベントを起動(具体的 62 // には EventListener が Changed に結合したメソッド ListChanged を呼ぶ)。 63 public override int Add(object value) 64 { 65 int i = base.Add(value); 66 OnChanged(EventArgs.Empty); // Empty の他に何がある??←無い。下記の説明を参照 67 return i; 68 } 69 // <ヘルプの EventArgs クラスの説明> 70 // このクラスにはイベント データは格納されません。このクラスは、イベントの発生時にス 71 // テータス情報をイベントハンドラに渡さないイベントによって使用されます。イベントハン 72 // ドラがステータス情報を必要とする場合、アプリケーションは、そのデータを保持するため 73 // に、このクラスからクラスを派生させる必要があります。 74 75 public override void Clear() 76 { 77 base.Clear(); 78 OnChanged(EventArgs.Empty); 79 } 80 81 public override object this[int index] 82 { 83 set 84 { 85 base[index] = value; 86 OnChanged(EventArgs.Empty); 87 } 88 } 89 } 90} 91 92namespace TestEvents 93{ 94 using MyEventTest; 95 96 class EventListener 97 { 98 private ListWithChangedEvent List; 99 100 // イベントのフック 101 // イベントの呼び出しの受け取りを開始するには、クライアントコードはまず、イベント 102 // から呼び出されるメソッドを参照するイベント型のデリゲート(以下のコードで言うと、 103 // new ChangedEventHandler(ListChanged) )を作成する。 104 // 次に、+= を使用して、イベントに接続される他のデリゲートに、このデリゲートを結 105 // 合する。 106 public EventListener(ListWithChangedEvent list) 107 { 108 List = list; 109 List.Changed += new ChangedEventHandler(ListChanged); 110 } 111 112 // イベントから呼び出されるメソッド。 113 private void ListChanged(object sender, EventArgs e) 114 { 115 Console.WriteLine("This is called when the event fires."); 116 } 117 118 // クライアントコードは、-= 演算子を使用してイベントからデリゲートを削除できる。 119 public void Detach() 120 { 121 List.Changed -= new ChangedEventHandler(ListChanged); 122 List = null; 123 } 124 } 125 126 // サンプルプログラムにもう一人 Listener を追加 127 class AnotherEventListener 128 { 129 private ListWithChangedEvent List; 130 131 public AnotherEventListener(ListWithChangedEvent list) 132 { 133 List = list; 134 List.Changed += new ChangedEventHandler(ListChanged); 135 } 136 137 private void ListChanged(object sender, EventArgs e) 138 { 139 Console.WriteLine("追加したもう一人の Listener に通知"); 140 } 141 142 public void Detach() 143 { 144 List.Changed -= new ChangedEventHandler(ListChanged); 145 List = null; 146 } 147 } 148 149 class Test 150 { 151 public static void Main() 152 { 153 ListWithChangedEvent list = new ListWithChangedEvent(); 154 155 EventListener listener = new EventListener(list); 156 AnotherEventListener anotherListener = new AnotherEventListener(list); 157 158 list.Add("item 1"); 159 list.Clear(); 160 listener.Detach(); // += した順に関係なく、不要となったデリゲートを -= で削除できる 161 list.Add("item 2"); 162 list.Clear(); 163 anotherListener.Detach(); 164 165 list.Changed += List_Changed; 166 list.Add("item 3"); 167 } 168 169 private static void List_Changed(object sender, EventArgs e) 170 { 171 Console.WriteLine("item 3 が追加された"); ; 172 } 173 } 174} 175 176 177// C# 言語では任意のデリゲート型のイベントを使用できるが、.NET Framework ではイベントに使用で 178// きるデリゲート型に厳密なガイドラインがある。適正なデリゲート型の EventHandler が .NET 179// Framework によって既に定義されている。上記のサンプルで、イベントのデリゲート型を宣言を削除 180// し、ChangedEventHandler を EventHandler と書き直せばよい。
投稿2023/02/22 02:44

退会済みユーザー
総合スコア0
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。