デリゲートは関数シグネチャを宣言し、クラスのイベントとして使用されると、登録された呼び出しターゲットのコレクションとしても機能します。イベントの += および -= 構文は、ターゲットをリストに追加するために使用されます。
イベントとして使用される次のデリゲートがあるとします。
// arguments for events
public class ComputerEventArgs : EventArgs
{
public Computer Computer { get; set; }
}
public class ComputerErrorEventArgs : ComputerEventArgs
{
public Exception Error { get; set; }
}
// delegates for events
public delegate void ComputerEventHandler(object sender, ComputerEventArgs e);
public delegate void ComputerErrorEventHandler(object sender, ComputerErrorEventArgs e);
// component that raises events
public class Thing
{
public event ComputerEventHandler Started;
public event ComputerEventHandler Stopped;
public event ComputerEventHandler Reset;
public event ComputerErrorEventHandler Error;
}
これらのイベントをサブスクライブするには、次のようにします。
class Program
{
static void Main(string[] args)
{
var thing = new Thing();
thing.Started += thing_Started;
}
static void thing_Started(object sender, ComputerEventArgs e)
{
throw new NotImplementedException();
}
}
引数は何でもかまいませんが、オブジェクトの送信者と EventArgs e は非常に一貫して使用される規則です。+= thing_started は、最初にターゲット メソッドを指すデリゲートのインスタンスを作成し、次にそれをイベントに追加します。
コンポーネント自体では、通常、イベントを発生させるメソッドを追加します。
public class Thing
{
public event ComputerEventHandler Started;
public void OnStarted(Computer computer)
{
if (Started != null)
Started(this, new ComputerEventArgs {Computer = computer});
}
}
イベントにデリゲートが追加されていない場合は、null をテストする必要があります。ただし、メソッド呼び出しを行うと、追加されたすべてのデリゲートが呼び出されます。これが、イベントの戻り値の型が void である理由です。単一の戻り値はありません。したがって、情報をフィードバックするには、イベント ハンドラーが変更する EventArgs にプロパティを設定します。
もう 1 つの改良点は、引数の型ごとに具体的なデリゲートを宣言するのではなく、汎用の EventHandler デリゲートを使用することです。
public class Thing
{
public event EventHandler<ComputerEventArgs> Started;
public event EventHandler<ComputerEventArgs> Stopped;
public event EventHandler<ComputerEventArgs> Reset;
public event EventHandler<ComputerErrorEventArgs> Error;
}