デリゲート (delegate) / 委譲

デリゲートとはタイプセーフティ (型の安全性) を保証したコールバック関数で、C++の関数ポインタに代わるものです。

構文

delegate 戻り値の型 デリゲート名( 引数, ... );

これは、C++で次のように記述することと同じです。

typedef 戻り値の型 (*関数ポインタ)( 引数, ... );

定義済みのデリゲート

基本的な形式のデリゲートがあらかじめ定義されているため、それを使えるならばあらためて定義する必要はありません。

  戻り値 引数 名前空間
MethodInvoker void なし System.Windows.Forms
Action void なし System
Action<T> void T System
Predicate<T> bool T System
Func<TResult> TResult なし System
Func<T, TResult> TResult T System

MethodInvoker

public delegate void MethodInvoker()
MethodInvoker デリゲート (System.Windows.Forms) | MSDN

Action

public delegate void Action()
Action デリゲート (System) | MSDN

Action<T>

public delegate void Action<in T>(T obj)
Action(T) デリゲート (System) | MSDN

Predicate<T>

public delegate bool Predicate<in T>(T obj)
Predicate(T) デリゲート (System) | MSDN

Func<TResult>

public delegate TResult Func<out TResult>()
Func(TResult) デリゲート (System) | MSDN
Func<T, TResult>
public delegate TResult Func<in T, out TResult>(T arg)
Func(T, TResult) デリゲート (System) | MSDN

使用方法

ここでは、次のメソッドをデリゲートから呼び出す方法を考えます。

public static int Callback(int x)
{
    return x * 2;
}

まずはこのメソッドの戻り値と引数の型が一致するように、delegateキーワードを用いてデリゲートを宣言します。

delegate int MyDelegate(int x);

この例ではデリゲート名がMyDelegateとして宣言されています。こうして宣言されたデリゲートは、

MyDelegate handler = new MyDelegate(Callback);

とすることでインスタンスを作成でき、

int a = handler(10);

とすることで、それに結びつけられたメソッドを呼び出せます。デリゲートの使用 (C# プログラミング ガイド) | MSDN

newの省略

C# 2.0以降ではnewを省略しメソッド名を指定するだけで、デリゲートをインスタンス化できます。方法 : デリゲートを宣言し、インスタンス化して使用する (C# プログラミング ガイド) | Microsoft Docs

  記述
C# 2.0より前
MyDelegate handler = new MyDelegate(Callback);
C# 2.0以降
MyDelegate handler =                Callback;

マルチキャスト デリゲート (multicast delegate)

1つのデリゲートに複数のメソッドを組み込み、それらを一括して呼び出せます。方法 : デリゲートを結合する (マルチキャスト デリゲート) (C# プログラミング ガイド) | MSDN

MyDelegate handler = new MyDelegate(Method1) + new MyDelegate(Method2)
handler += new MyDelegate(Method3);

handler(); // Method1とMethod2とMethod3が呼ばれる

匿名関数 (Anonymous Functions)

匿名メソッド (Anonymous Methods)

C# 2.0以降ではデリゲートから呼び出すメソッドをインラインで記述することで、メソッドの定義を省略できます。

C# 3.0以降では、メソッドの引数を使用するならばラムダ式を用います。この匿名メソッドが必要となるのは、引数を省略する場合のみです。

たとえばデリゲートが、

delegate int MyDelegate(int x, int y);

のように定義されているとき、通常は

public int Callback(int x, int y)
{
    return x + y;
}

のようにコールバック メソッドを定義した上で、それを

MyDelegate handler = new MyDelegate(DelegateMethod);
int a = handler(2, 3);

のようにデリゲートをインスタンス化して利用します。一方で匿名メソッドではコールバック メソッドの定義を省略し、

MyDelegate handler = delegate (int x, int y) { return x + y; };
int a = handler(2,3);

のように記述できます。これをイベントに適用すると、次のようにコールバックメソッドを省略できます。

button.Click += delegate( object sender, EventArgs e )
{
    // このメソッドには名前がない。匿名メソッド
};

このとき引数が不要ならば、かっこごと省略できます。

ラムダ式 (lambda expression)

ラムダ式はC# 3.0以降でサポートされます。

たとえば次のようにデリゲートが宣言されていると、

delegate int MyDelegate(int x);

ラムダ式ではメソッドを定義することなく、これを次のように記述できます。

MyDelegate handler = x => { return x * 2; };

int a = handler(10);

構文

下表のように2つの形式があります。

形式 構文
式形式 (Expression Lambdas)
(parameters) =>  expression
ステートメント形式 (Statement Lambdas)
(parameters) => {expression;}

また、引数の数によっても形式が異なります。

パラメータの数ごとの記述形式
パラメータの数
なし
() => {}
1つ
(x) => {}
 x  => {}
かっこを省略できる
2つ以上
(x, y) => {}
MSDN (Microsoft Developer Network) から検索