C#のラムダ式【=>】って何?

C#のコードを眺めていると

 

 

var ret = list.Select( n => 0 < n );

 

のような書き方を見る事があります。

この、メソッドの引数の部分。C#に慣れていない人は、なにこれ?ってなるんじゃないでしょうか?

 

これ、C#3.0から導入されたラムダ式と言います。

今回はこのラムダ式についてまとめてみようと思います。

その前にデリゲート(delegate)を理解する

ラムダ式を理解する為には、まずデリゲート(delegate)を理解する必要があります。

 

デリゲートを簡単に説明すると、関数変数のように扱う為のものです。

 

変数のように扱えれば、関数の引数に関数を渡す事ができます。

引数に関数が渡せれば、計算式の一部だけを簡単に差し替える事ができます。

 

 

※デリゲートを更に詳しく知るにはC#のデリゲート (delegate) って何?をご覧ください

コードサンプル

以下の例はList<int>を継承したクラスですが、条件に合う項目だけを抜き出すSelectメソッドを作ってみました。この「条件に合う」という部分にdelegateを使っています。

    public delegate bool TestDelegate(int n);


    public class TestList : List<int>
    {
        public TestList Select(TestDelegate func)
        {
            var list = new TestList();
            foreach (var obj in this)
            {
                if (func(obj))
                {
                    list.Add(obj);
                }
            }
            return list;
        }
    }

 

このクラスを使った例が以下のものです。

匿名メソッドを記述して、値が0以上の項目を抜き出しています。

            var list = new TestList();
            list.Add(0);
            list.Add(1);
            list.Add(2);

            var result = list.Select(
                delegate (int n)
                {
                    if (0 < n)
                        return true;
                    else
                        return false;
                });

 

※匿名メソッドを更に詳しく知るにはC#のデリゲートお手軽にする匿名メソッドをご覧ください

ラムダ式は匿名メソッドを簡略化したもの

デリゲートが分かったところでラムダ式の話に移ります。

ざっくり言うとラムダ式は匿名メソッドを簡略化して記述したものになります。

上記の例を少し簡単にしてみましょう。

            var list = new TestList();
            list.Add(0);
            list.Add(1);
            list.Add(2);

            var result = list.Select(
                delegate (int n)
                {
                    return (0 < n);
                });

このdelegateキーワードを演算子=>に置き換えたものがラムダ式です。

            var result = list.Select(
                (int n) =>
                {
                    return (0 < n);
                });

C#には型推論という機構があります。

この型推論機構のおかげでラムダ式は、引数の型の記述を省略する事ができます。

            var result = list.Select(
                (n) =>
                {
                    return 0 < n;
                });

関数の中身が1行の場合、{}returnも省略する事ができます。

            var result = list.Select((n) => 0 < n);

delegateの引数が1つだけの場合は()も省略する事ができます。

            var result = list.Select(n => 0 < n);

ちなみにdelegateの引数が2つの場合は()が必要になります。

    public delegate bool TestDelegate(int n1, int n2);
            var result = list.xxxx((n1, n2) => (0 < n1) && (0 < n2));