ラムダ式

ラムダ式 Lambda expressions は、匿名メソッドと同じようにデリゲート型のインスタンスを生成します。専用のメソッドを別に定義することなく、式の中でメソッドを定義することができます。ラムダ式はLISP言語のような関数型言語では古くから用いられている機能で、Python言語などでも用いられています。

ラムダ式の構文

lambda-expression:
    (   lambda-parameter-listopt   )   =>   lambda-expression-body
    implicitly-typed-lambda-parameter   =>   lambda-expression-body

lambda-parameter-list:
    explicitly-typed-lambda-parameter-list
    implicitly-typed-lambda-parameter-list

explicitly-typed-lambda-parameter-list
    explicitly-typed-lambda-parameter
    explicitly-typed-lambda-parameter-list   ,   explicitly-typed-lambda-parameter

explicitly-typed-lambda-parameter:
    parameter-modifieropt   type   identifier

implicitly-typed-lambda-parameter-list
    implicitly-typed-lambda-parameter
    implicitly-typed-lambda-parameter-list   ,   implicitly-typed-lambda-parameter

implicitly-typed-lambda-parameter:
    identifier

lambda-expression-body:
    expression
    block

ラムダ式が生成するのはデリゲート型のインスタンスなので、性質的には匿名メソッドに似ています。ラムダ式では、最初にメソッドが受け取る仮パラメータリストを宣言し、その後 => トークンに続いてメソッドの本体を記述します。もっとも単純なラムダ式は、次のようなものになるでしょう。

() => { メソッド本体 }

上記のラムダ式は、パラメータを受け取らず、戻り値を返さないメソッドへのデリゲート型インスタンスを返します。匿名メソッドで例えるならば、次のものと同義です。

delegate { メソッド本体 }

ラムダ式は、生成するメソッドが受け取る仮パラメータの型を明示的に宣言するexplicitly-typed-lambda-parameter-listと、暗黙的に宣言するimplicitly-typed-lambda-parameter-listが用意されています。明示的に型付けされたラムダ式のパラメータリストは、通常のメソッドの宣言と同じです。explicitly-typed- lambda-parameterにあるように、各仮パラメータに修飾子、型、変数名をそれぞれ指定します。

(int x, int y) => { return x + y; }

上記の例は、2つの整数型パラメータxとyを受け取って、それらを加算した結果を返すというラムダ式です。

これに対して、暗黙的に型付けされたラムダ式のパラメータリストは修飾子や型を指定しません。受け取るパラメータの識別子だけを指定します。

(x, y) => { return x + y; }

上記は、暗黙的に型付けされたパラメータリストを使ったラムダ式です。xとyパラメータの型が省略されています。この場合、ラムダ式の結果を互換性のあるデリゲート型から推論し、変換してくれます。また、暗黙的な型パラメータが1つだけの場合は( )を省略することができます。

x => { return x; }

この場合でも、構文におけるlambda-expressionの2番目の項が適用されるため問題ありません。複数の仮パラメータを持つパラメータリストを指定する場合は( )が必要になります。

サンプル04

delegate void D1();
delegate int D2(int x);

class Test
{
    static void Main(string[] args)
    {
        D1 m1 = () => { System.Console.WriteLine("ごきげんよう"); };
        D2 m2 = (int x) => { return x + 1; };
        D2 m3 = x => { return x * 2; };

        m1();
        System.Console.WriteLine("m2()=" + m2(10));
        System.Console.WriteLine("m3()=" + m3(100));
    }
}

実行結果

ごきげんよう
m2()=11
m3()=200

ラムダ式の本体lambda-expression-bodyに文を記述したい場合はブロック文blockを用いますが、メソッドの結果となる式expressionだけを記述することも可能です。例えば、受け取ったパラメータの値に1を加えた結果を返すメソッドへのデリゲート型のインスタンスは、次のように生成することができます。

x => x + 1

ラムダ式は、比較処理やソートなどでアルゴリズムを選択できるような仕組みを実現するために、一部の演算処理を委ねる設計の場合に有効です。ラムダ式の登場によって、メソッドのパラメータからコールバック用のデリゲート型インスタンスを受け取る設計を受け入れやすくなるでしょう。