【C#】イベントハンドラの処理をラムダ式で書く


C#でイベント関連の処理を書く場合に、
簡単な処理を行うだけなのにわざわざ関数を用意するのが手間だったので
ラムダ式で書いてみたのでその際の覚書。

ラムダ式でイベント処理
btnOK.Click += (sender, e) => { MessageBox.Show("OKボタンを押下!"); };

この記述の問題点としてはイベント解除が出来ないこと。
まぁ実際はボタン押下イベントとかは動的に登録/解除することはあんまりないと思うんだけど。

で、その場合にどうするかというと、以下のように書けばOK。

ラムダ式でイベント登録と解除
EventHandler handler = null;
handler = (sender, e) => { MessageBox.Show("OKボタンを押下!"); };
// 登録
btnOK.Click += handler;

// 解除
btnOK.Click -= handler;

要するにイベント解除する時は登録時と同じものを指定する必要があるので
EventHandlerを用意しておこう、ということ。

個人的にこの手法で便利だったのは、
ローカル変数をイベント処理内で参照出来る点。

具体的には元々ファイル検索みたいな処理を別スレッドで実行して、
処理が終わったらイベントが発行されるクラスがあって、
それを流用する際に同期的に使用する必要があったケース。
処理が終わったイベントで終了フラグをOnにして、
メインスレッド側ではその終了フラグがOnになるまで待機、みたいな処理を組む場合に
関数内て定義した情報だけで完結出来る。

別スレッドの処理待ち
bool isFinished = false;       // 処理完了フラグ
EventHandler finish = null;
finish = (object sender, EventArgs e) => { isFinished = true; };// 検索完了フラグを立てるだけ
var searcher = new Searcher(); // 検索用クラス
searcher.Finished += finish;   // 検索用クラスに完了イベントを登録
searcher.Start();              // 検索開始

// 検索が終わるまでここで待つ
while(false == isFinished)
{
    Task.Delay( 100 ).Wait();
}

// イベントハンドラ破棄
searcher.Finished -= finish;

従来通りに関数を用意していた場合は処理完了フラグをクラスのメンバとして持つ必要がある。
でもこの処理でしか使わないのであればローカルに留めておきたいので
この書き方は有りだと思います。