LINQの引数(分解して考えます)

2023年1月27日

LINQは、配列やListのデータを処理するのに便利な機能です。
LINQのWhereメソッドから、匿名メソッド(無名関数)をみていきましょう

次のコードは、整数リストから、0より大きいデータを抽出して表示するものです。

List<int> scores = new List<int> { -1, -2, 0, 1, 2 };

var scoresPositive = scores.Where(n => n > 0);

foreach (var score in scoresPositive)
{
    Console.WriteLine(score);
}

結果

1
2

Whereメソッドの条件として、(n => n > 0)のラムダ式が使われています。引数は、次のようなメソッドが入っています。

整数を引数として、0より大きければtrue、そうでなければfalseを返すIsPosiveメソッド

これをコードで書くと次のようになります。

static bool IsPositive(int n)
{
    bool result;

    if (n > 0)
    {
        result = true;
    }
    else
    {
        result = false;
    }

    return result;
}

result変数を省略すると、

static bool IsPositive(int n)
{

    if (n > 0)
    {
        return true;
    }
    else
    {
        return false;
    }
}

さらに省略すると、

static bool IsPositive(int n)
{
    return n > 0;
}

このコードを全てコメントにします。この後、インテリセンスを使って自動生成してみますが、そのときのコードと比較してみましょう

// static bool IsPositive(int n)
// {
//     return n > 0;
// }

LINQ式を見直します。

var scoresPositive = scores.Where(n => n > 0);

を、次のように変更します。

var scoresPositive = scores.Where(IsPositive);

VisualStudioのインテリセンスで、「メソッドを生成」を選択し、自動生成します。

private static bool IsPositive(int arg)
{
    throw new NotImplementedException();
}

コードを差し替えると同じになります。

private static bool IsPositive(int n)
{
    return n > 0;
}

これでも、実行すると同じ結果が得られます。このことから、メソッドが代入されているのがわかります。

今度は、Whereの引数のIsPositiveを削除し、()のところを改行します。

var scoresPositive = scores.Where
(
);

()の中にメソッドを丸ごと入れてしまいます(エラーにはなります。)

var scoresPositive = scores.Where
(
    private static bool IsPositive(int n)
    {
        return n > 0;
    }
);

private static bool IsPositiveを、delegateに差し替えます。

IsPositiveという、名前が消えましたね。これが匿名メソッド(無名関数)と呼ばれる理由です。

var scoresPositive = scores.Where
(
    delegate (int n)
    {
        return n > 0;
    }
);

ここから、ラムダ式に変更を試みます。

delegateを消して、ラムダ演算子(=>)を追加します。

var scoresPositive = scores.Where
(
    (int n) =>
    {
        return n > 0;
    }
);

int型が推論されるため、消すことができます。

var scoresPositive = scores.Where
(
    (n) =>
    {
        return n > 0;
    }
);

ブロック内のコード行が1行の場合、{}とreturnと;をセットで消すことができます。動作しますよね。?

var scoresPositive = scores.Where
(
    (n) =>
            n > 0
);

引数が、1つの場合、(n)の()を外せます。改行を詰めれば、次のようになります。

 var scoresPositive = scores.Where(n => n > 0);

はい、これで、LINQとラムダ式のペア完成です。

C#,LINQ

Posted by hidepon