デリゲート (プログラミング)
デリゲートは、オブジェクトインスタンスへの参照とメソッドへの参照をペアにしてカプセル化するものである。概念としてはC言語やC++の関数ポインタに近いが、デリゲートは完全なオブジェクト指向である。型安全であるという特徴がある。
Object Pascal(Delphi)の「インスタンスのメソッドへのポインタを格納する、メソッドポインタ」と同様のものである。また、Microsoft Visual J++も、Javaと非互換のデリゲートを導入したが、.NET Frameworkのデリゲートはこれらを発展させたものである。
なお、C++における「クラスの非静的メンバ関数を指す関数ポインタ」は、関数呼び出し時にそのクラスのインスタンスを必要とする。デリゲートのようにオブジェクトとして扱うためにはstd::functionなどの関数オブジェクトによるカプセル化が必要となる。
デリゲートにより、メソッド単位のコンポジション (合成) が可能となる。デリゲートは主に、イベント処理での活用(コールバック処理のカスタマイズ)を想定している。
こうして生成したデリゲート型オブジェクトは、通常のメソッドのように直接実行することができる。
なお、上記は以下のInvokeメソッド呼び出しに対する糖衣構文である。Invokeメソッドはコンパイラによって自動生成される。
しかし、デリゲートの真価が発揮されるのはイベントと併用した時である。イベントは、次のように宣言する。
こうして宣言したイベントには、+= 演算子と -= 演算子によって、デリゲート(イベントハンドラ)を追加したり削除したりすることができる。
イベントハンドラの追加が += 演算子によって行われることから推測できるように、1つのイベントには複数のイベントハンドラを登録することができる。
次のようにしてイベントの定義されたクラスの内部からイベントを起こすと、登録したイベントハンドラがまとめて実行される。
実行される順番は登録順とは関係なく、未定義である。
なお、eventで修飾されていない通常のデリゲート型メンバーと異なり、SomeEventにはクラス外部から=演算子で直接再代入をすることはできない。また、SomeEventが定義されたクラス内からしか呼び出せない。この制約により、誤ってイベントサブスクリプションをクリアしてしまうことを防止したり、イベントハンドラーを呼び出す責任の所在を明確にしたりすることができる。