[解決済み】ラムダのイベントハンドラを削除する方法【重複あり
2022-04-01 11:23:55
質問
<余談
最近、ラムダを使って簡単なイベントハンドラを作ることができることを発見しました。例えば、次のようなクリックイベントを受信することができます。
button.Click += (s, e) => MessageBox.Show("Woho");
でも、どうやって配信を停止するのでしょうか?
解決方法は?
C#の仕様では、2つの匿名関数(匿名メソッドまたはラムダ式)がある場合、そのコードから同等のデリゲートを作成できる場合とできない場合があると明示されています(IRC)。(2つのデリゲートは、同じターゲットを持ち、同じメソッドを参照していれば、等しい)。
念のため、使用したデリゲートインスタンスを覚えておく必要がありますね。
EventHandler handler = (s, e) => MessageBox.Show("Woho");
button.Click += handler;
...
button.Click -= handler;
(仕様の該当部分が見つからないのですが、C#コンパイラが積極的に等しいデリゲートを作成しようとするのを見ると、かなり驚きますね。確かにそれに頼るのは賢明ではないだろう)。
それが嫌なら、メソッドを抽出する必要があります。
public void ShowWoho(object sender, EventArgs e)
{
MessageBox.Show("Woho");
}
...
button.Click += ShowWoho;
...
button.Click -= ShowWoho;
ラムダ式を使って自分自身を削除するイベントハンドラを作りたい場合は、少し厄介です。ラムダ式自体の中でデリゲートを参照する必要がありますが、単純に "ローカル変数を宣言してラムダ式を使ってそれに代入する" では、変数は確実に代入されないため、それを行うことができません。このような場合は、まず変数にNULL値を代入して回避するのが一般的です。
EventHandler handler = null;
handler = (sender, args) =>
{
button.Click -= handler; // Unsubscribe
// Add your one-time-only code here
}
button.Click += handler;
残念ながら、イベントはきれいに表現できないので、これをメソッドにカプセル化することも簡単ではありません。一番近いのは次のようなものだろう。
button.Click += Delegates.AutoUnsubscribe<EventHandler>((sender, args) =>
{
// One-time code here
}, handler => button.Click -= handler);
の中で実装するのは難しいでしょう。
Delegates.AutoUnsubscribe
というのも、新しい
EventHandler
(これは単なる一般的な型引数になる)。可能ですが、面倒です。
関連
-
[解決済み】Visual Studio: 操作を完了できませんでした。パラメータが正しくありません
-
[解決済み] event.preventDefault() vs. return false
-
[解決済み] 複数の例外を一度にキャッチする?
-
[解決済み] IDisposable インターフェースの正しい使用法
-
[解決済み] C#がforeachで変数を再利用するのは理由があるのか?
-
[解決済み] 特定のプロパティに対するLINQのDistinct()
-
[解決済み] Java 8 List<V> を Map<K, V> に変換する。
-
[解決済み] Distinct() with lambda?
-
[解決済み] あるイベントからすべてのイベントハンドラを削除する方法
-
[解決済み】C++11のラムダ式って何?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】「未割り当てのローカル変数を使用」とはどういう意味ですか?
-
[解決済み】指定されたキャストが有効でない?
-
[解決済み】コンパイルエラー「未割り当てのローカル変数を使用しています」が発生したのはなぜですか?
-
[解決済み】パディングが無効で、削除できない?
-
[解決済み】Unity3DでOnTriggerEnterが動作しない件
-
[解決済み】C# - パスに不正な文字がある場合
-
[解決済み】値をNULLにすることはできません。パラメータ名:source
-
[解決済み】「namespace」なのに「type」のように使われる。
-
[解決済み】プロセスが実行されているかどうかを知るには?
-
[解決済み】C#の無名メソッドの購読を解除する