by WebSurfer
2012年7月2日 22:28
C# を使った .NET Framework アプリでのイベントとハンドラの宣言、定義の方法を忘れかけていて余計な時間がかかったので、整理して、備忘録として簡単に書いておきます。
まず、イベントを宣言するには、その前にデリゲート型の宣言が必要です(EventHandler デリゲートのようにクラスライブラリに用意されている場合は不要です)。
C# のデリゲートは、C や C++ の関数ポインタと同じと考えればよいと思います。以下の例は、Object 型と EventArgs 型の引数を持つデリゲート型 ChangedEventHandler の宣言です。
public delegate void
ChangedEventHandler(object sender, EventArgs e);
上の構文は、メソッド宣言の構文と同様ですが、delegate キーワードによって、ChangedEventHandler がデリゲート型であることをコンパイラに通知しています。
規約により、.NET Framework のイベントデリゲートは、そのイベントの発生元(上の例では sender)と、そのイベントのデータ(上の例では e)という 2 つのパラメータを持ちます。
デリゲートを定義した後、イベントの実装は以下のように行います。細かい説明はコメントを参照してください。
public class MyClass : ArrayList
{
// デリゲートを用いてイベントを宣言。クラスの外からは
// 公開フィールドのように見えるが、アクセスには制限が
// あり、実行できるのは以下の処理のみ。
// ・新しいデリゲートの結合
// ・結合されたデリゲートの削除
public event ChangedEventHandler Changed;
// イベントを起動するメソッド OnChanged を作成し
// ておき、必要なタイミングで呼び出す。イベントは、イ
// ベントを宣言したクラスの中からしか起動できない。そ
// れゆえ、protected として作成し、派生クラスがイベン
// トを起動できるようにする。
protected virtual void OnChanged(EventArgs e)
{
// ハンドラがイベントにアタッチされてない場合 null
// になるので、起動する前に null でない事を確認。
if (this.Changed != null)
{
this.Changed(this, e);
}
}
// 例えば、何かを追加したタイミングでこのイベントを発
// 生させたいときは、以下のようにする。
public override int Add(object value)
{
int i = 0;
// 何かの処置
OnChanged(EventArgs.Empty);
return i;
}
}
ここまでの宣言、定義で、MyClass.Add メソッドが起動された時、MyClass.Changed イベントが発生します。
ただし、ハンドラの定義、ハンドラのイベントへのアタッチがないので、それ以上は何も起こりません。
ハンドラの定義とイベントへのアタッチは以下の例のようにします。
public class EventListener
{
private MyClass _myClass;
public EventListener(MyClass myClass)
{
this._myClass = myClass;
// ハンドラをイベントにアタッチ
this._myClass.Changed +=
new ChangedEventHandler(MyClass_Changed);
}
// ハンドラの定義
private void MyClass_Changed(object sender, EventArgs e)
{
// 何かの処理
}
}