C# で LINQ

C# の最大の特徴である LINQ 。 やはり LINQ を使いこなさないと C# を使えるとは言えないのではないか。 ということで本格的に LINQ を学ぶことにした。

以下のサイトが非常に参考になった。

C# やるなら LINQ を使おう | プログラマーズ雑記帳

LINQ には SQL のようなクエリー式と 通常のメソッド形式の標準クエリー演算子の 2 つの書き方ができます。 その特異さのため、 LINQ というとクエリー式に目が行きがちです。 しかし、 私の思う LINQ の魅力はそんなところにはありません。 SQL に馴染みがある人はクエリー式で書くのもいいとは思いますが、 私はほとんどクエリー式は使ったことがなく、この説明でも標準クエリー演算子の方で説明していきます。

例えば、以下の様な配列がある。

参考:LINQ クエリ式 (C# プログラミング ガイド)

int[] scores = new int[] { 97, 92, 81, 60 };

確かに、C#LINQ というと、まず以下のようなクエリ式を想像する。

var scoreQuery =
        from score in scores
        where score > 80
        select score;

これは scores の中から 80 より大きい要素を抽出するクエリである。 実行するには foreach を使う。

foreach (var i in scoreQuery)
{
    Console.Write(i + " ");
}            
// 結果
// 97, 92, 81

しかし、実際には以下の様にメソッド形式で使われていることが多い気がする。

var scoreQuery = 
        scores.Where(score => score > 80).Select(score => score);

SQL は個人的にあまり使わないので、後者のほうがわかりやすい。

しかも、クエリ式だと from から始まって select で終わる必要があるが、 メソッド形式だと Where 単体とか Select 単体でも使えるし、 そのことがわかりやすい。

以下のサイトで、クエリ式がどのようにメソッド呼び出しに変換されているかがわかる。

標準クエリ演算子(クエリ式関係) (C# によるプログラミング入門)

from score in scores が scores となる、というのが結構びっくり。 でもよく考えてみるとそうだよな…。

このことからも、クエリ式は SQL っぽく見せたシンタックスシュガーであることがわかる。

また、メソッド形式で重要なのがラムダ式

上記のWhereでもSelectでもラムダ式を使っている。

先にラムダ式については勉強してたから抵抗はないけど、最初にラムダ式を見たときは拒絶反応があった気がする。

ラムダ式はわかってしまえばとても簡単で、ただの無名関数である。

わかりづらいと感じるのはきっと書き方のせい。

関数の引数 => 関数の本体

という構成。

ただ、引数が1つの場合は引数の()を省略でき、関数の本体が1行の場合は関数の本体の{}を省略できるというルールがある。

つまり、ちゃんと書くと以下のようになる。

(関数の引数) => {関数の本体}

上記の例は以下と同じ。

var scoreQuery = 
        scores.Where((score) => {return score > 80;})
        .Select((score) => {return score;});

関数本体は、{}をつける場合は return も ; も必要となる。 わかりやすいけど冗長になる。

Whereは、引数1つで、boolを返す関数を引数にとることがわかる。

Selectは、引数1つで、ある型を返す関数を引数にとることがわかる。

引数には、元のソースの要素が1つずつ入る。

LINQ はわかってくると楽しい。

これからはメソッド形式を積極的に使っていこう。