技術とか戦略とか

IT技術者が技術や戦略について書くブログです。

C#:イベントハンドラとは

イベントハンドラとはC#で標準で用意されている文法であり、イベント送受信の処理を記述するために用意されています。
 
クラスAでボタンのクリック等のイベントを発行する

クラスBはクラスAからイベントを受け取り業務処理を行う

クラスBは業務処理終了時にクラスAに何かしらの処理を返す
 
という動きを実現するための文法です。
 
文法的にはdelegateの応用であり、
public delegate void EventHandler(object sender, EventArgs e);
というdelegateが標準で用意されていると考えて問題ありません。
(自分で上記の定義を行っても同じ動きをします)
なお、"object sender"とは業務処理を行ったオブジェクト、"EventArgs e"とはイベント発行側のクラスに返すデータ、を指します。
 
上記の通り、イベントハンドラとは、引数に object sender と EventArgs e を持つdelegateです。
そのため、delegateを理解していれば、イベントハンドラの文法も理解できます。
自分で使うかどうかは別として、Visual StudioWindows Form を作成した時に自動生成されるソースコードや、他の人のソースコードを読む分には問題ないでしょう。
 
以下、サンプルコードです。
 
【サンプルコード】
・Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace EventHandlerTest
{
    class Program
    {
        // イベント発生(exe実行)
        static void Main(string[] args)
        {
            EventReceiver eventReceiver = new EventReceiver();
            // イベントハンドラの登録
            eventReceiver.EventHandlerObj += new EventHandler(NoticeOfEnd);
            eventReceiver.Start();
            Console.ReadKey();
        }

        // イベント終了時に実行して欲しい処理
        static void NoticeOfEnd(object sender, EventArgs e)
        {
            // "object sender"は処理を行ったオブジェクト
            Console.WriteLine("処理実行オブジェクト:" + sender.ToString());

            // "EventArgs e"はイベント終了時に返されるデータ(今回は無し)
            if (e.Equals(EventArgs.Empty))
            {
                Console.WriteLine("返されるデータ:" + EventArgs.Empty);
            }

            // 終了通知
            Console.WriteLine("Notice Of End");
        }
    }
}
 
・EventReceiver.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace EventHandlerTest
{
    class EventReceiver
    {
        // 下記の定義がされたdelegateが予め用意されている。
        // public delegate void EventHandler(object sender, EventArgs e);

        // データを持たないイベントデリゲートの宣言
        public event EventHandler EventHandlerObj;

        // 当クラスを継承することを考え protected virtual
        // (オーバーライド可能)
        protected virtual void EndProcedure(EventArgs e)
        {
            // 登録されたイベントハンドラがあれば、それを実行する。
            if (EventHandlerObj != null)
            {
                EventHandlerObj(this, e);
            }
        }

        // イベント受取時の処理
        public void Start()
        {
            Console.WriteLine("Business Logic");
            System.Threading.Thread.Sleep(3000);

            // 今回はEventArgsで返すデータは無し。
            // 返すデータがある場合はEventArgsを継承して定義し、
            // 継承したEventArgsを使うEventHandlerも独自に定義する。
            EndProcedure(EventArgs.Empty);
        }
    }
}
 
【実行結果】
Business Logic
処理実行オブジェクト:EventHandlerTest.EventReceiver
返されるデータ:System.EventArgs
Notice Of End