2014/09/01

[C#]LINQを覚えた(ラムダ式と型推論も)

このエントリーをはてなブックマークに追加
しばらくC#から遠ざかっていたわけですが、LINQを覚えました。
C#はじゃんじゃん記法が追加されていて、いつの間にか完全に取り残されてしまっていました。
今更LINQについて書きます。

LINQの存在はもちろん知ってはいたけれど、ちょっと他の言語との乖離が気持ち悪くて踏み込めないでいました。とてつもなく便利だ、という噂も入ってくるので気にはなっていました。
最近、ひょんなことから、しばらくぶりにC#を書いてて、LINQとやらもちょっと使ってみたところ、何ともあっさり吸収できた。なんてことなかった。
そのときの、自身のブレイクスルーを書いておくことにします。

LINQについておさらい

LINQはリンクと呼びます。

Wikipedia LINQ-総合言語クエリ

総合言語クエリと聞いても何のことやらわかりませんが、2007年末に出現しました。そんな前なのです。.NET Framework 3.5(C# 3.0/Visual Basic 9.0)から、LINQ(統合言語クエリ)という書き方ができるようになりました。SQLみたいな書き方でデータ集合に問い合わせができるというものです。
あんまり詳しくここでは説明しませんが、サンプルコードだけ書いておきます。

①foreach
IEnumerable<Color> colors = CreateColors();
List<Color> newColors = new List<Color>();
foreach(Color color in colors ){
    if(color.isYellow()){
        newColors.Add(color);
     }
}

上のforeachのコードは、配列colorsから、黄色のものだけを抽出して、newColorsという新しい配列を作成するというコードです。
上のコードをざっくりLINQでの書き換えると次のようになる。(細かいところはさておき)

②LINQ(クエリ式)
IEnumerable<Color> colors = CreateColors();
IEnumerable<Color> newColors =
     from color in colors 
     where color.isYellow()
     select color;
LINQには、クエリ式とメソッド呼び出しの書き方があります。上はクエリ式。

③LINQ(メソッド式)
IEnumerable<Color> colors = CreateColors();
IEnumerable<Color> newColors = colors.Where(c => c.isYellow());

どちらも動作の仕組みは同じ(コンパイラがループに展開するだけ)です。
foreachのnewColors がListなのは、新しい配列にするのに必要だっただけで他意はありません。LINQをListとするためには、ToArray()を呼び出せばList型にしてくれます。
さらっと流すつもりですが、ここは結構大切なところなので、遅延実行について学習するとよいかと思います。

自分は、メソッド呼び出しのほうが書きやすかった。
ラムダ式と呼ばれる(c => c.isYellow())という記述が鬱陶しく思うかもしれません。だけど書き方のパターンを知ってしまえば、応用なんて後からついてきます。

ついでにラムダ式と型推論についてのブレイクスルー

ラムダ式もあんまり書いてなかったので、一緒に覚えました。
ラムダ式も、これがこう省略されて最終的にこう書ける、という順序説明があるのだけど、そんなもん全部すっとばして、こう書けるという一点だけを覚えて、後は、慣れてから応用を伸ばしていけばいいように思いました。理解しないまで書かないという制限が、姿勢を委縮させる気がします。正直、自分も、このあたりよくわからんが、まあ動いています。
それから、戻り値にvarを書くサンプルがありますが、まだちょっと違和感を覚えます。かと言って、全部強い型付けで書くと長ったらしいコードになるのは解っている。
var newColors = colors.Where(c => c.isYellow());

このくらいがいいかなと。
IEnumerable<Color> newColors = colors.Where(c => c.isYellow());
つまり、戻り値となる型を最初に特定して宣言している意味があって、型の整合性が取れなかったらコンパイルするタイミングで解るということですね。LINQに慣れない状態でvarを連発すると、戻り値が全然違ってたりするのが怖い。

[雑記] 型推論の是非
http://ufcpp.net/study/csharp/sp3_var.html

強い型付けであってほしい、と最初は感じものの、全部varでもわりと問題ないそうです。
このあたりは、この先、自分も書きながら調整していこうと思います。

長いのでこの辺で、次に続く。
[C#]LINQを使用するメリット

0 件のコメント :

コメントを投稿