Unityや.Net Coreのおかげで、windowsソフトの開発以外でも、いっちょC#使ってみっかという人は増えてきていると思う(増えてほしい)。
アンダース・ヘルスバーグによってめちゃめちゃ使いやすく設計されているC#にあって、他の言語と一線を画した使いやすさはLINQのおかげと言っても過言ではない。
しかしながらLINQは、「覚えれば使いやすいけれど、覚えるまで使いにくい」という、自転車のような技術でもある。
.Netの拡がりに影響を受け、C#を触ることになった人がLINQ界にスマートに入れるよう、基本のキの字を書こうと思う。
LINQのありがたみ
ORマッピングでやっているようなことをやれると書くと、Webな人たち以外にはハテナ。わかりやすくLINQの有り難みを書くと、何重ものforeachループ、追い切れないフラグで作っていた処理を英語を書くかのごとく実装できることにある。
※LINQにハマりすぎてLINQ星人となった御仁は、ループ処理を見ると寒気がするそうな。
そんなLINQには、パッと考えただけでもこれだけのメリットがある。
- ループ処理が短く書ける。
- ループ処理よりもネストが浅くなる。
- ループ処理よりも分かりやすい。
- ループ処理を簡単に並列処理にできる。
こう並べてみると、読みやすさ=リーダブルコードに繋がる利点が多いな。
ソースコードは実装よりも保守の期間、すなわち他の人の目に触れる期間の方が長いものだから、読みやすさというものは何を置いても大事にしたい。その点、昔ながらのループ処理をLINQで書くだけで、グッと読みやすくなるのだから、使わない手は無い。
C#ビギナーの諸兄にあっては、foreachと打ちたくなる手をグッと堪え、LINQでどう実現できるかを考えていただきたい。
そのときに必ず気になるのが、「これはLINQで書くべき処理なのか?」ということ。
LINQでは副作用のないコードを書くべきなので、LINQの処理の中でメンバー変数やプロパティを書き換える必要がある場合はLINQを使うべきでない。
まずはこれだけ覚える
LINQには様々なメソッドがあるけれど、はじめから全て使いこなすのは難しい。そこでまずは基本的な4つのメソッドだけを覚えるのをおすすめする。
- Any
- Select
- Where
- FirstOrDefault
Any
要素の集まりから、指定の条件にあった要素が一つでもあるかどうかを問うメソッド。
作例では、0, 1, 2, 3, 4, 0という数値のコレクションから、4と5を探している。
当然、4はコレクションに含まれていて、5は無い。
1 2 3 4 5 6 7 8 9 10 11 |
var numbers = new[] { 0, 1, 2, 3, 4, 0 }; // Any var fourExist = numbers.Any(number => number == 4); var fiveExist = numbers.Any(number => number == 5); // True Console.WriteLine("Does four exist? : " + fourExist.ToString()); // False Console.WriteLine("Does five exist? : " + fiveExist.ToString()); |
Select
LINQで一番お世話になるのがこいつ。Select先輩チーっす!
コレクションの要素一つ一つを変換(射影)するメソッド。
下の例でいえば、先ほどの数値の集まりに対して、各数値に1を足している。
この変換という処理とSelectというネーミングが中々結びつきにくいけれど、そこは偉い人が考えたことなので粛々と受け入れよう。
1 2 3 4 5 6 7 8 |
// Select var addedNumbers = numbers.Select(number => number + 1); // 1, 2, 3, 4, 5, 1 const string separator = ", "; Console.WriteLine( "Added Numbers : " + string.Join(separator, addedNumbers.Select(number => number.ToString()))); |
Where
Selectよりグッと簡単になって、コレクションの中から要素を探すメソッドがこのWhere。
作例では、4未満の数値を探している。
コレクションには、0, 1, 2, 3, 4, 0 が含まれていたから、当然、0, 1, 2, 3, 0が見つかる。
LINQ使いたてのころ、一番多用するのも本メソッド。しかしながら、Anyや後述のFirstOrDefaultでいい場合が多く、慣れてくるとあまり使わなくなる。
そのコード、Whereいらんくないけ?
1 2 3 4 5 6 7 |
// Where var numbersUnderFour = numbers.Where(number => number < 4); // 0, 1, 2, 3, 0 Console.WriteLine( "Numbers Under Four : " + string.Join(separator, numbersUnderFour.Select(number => number.ToString()))); |
FirstOrDefault
コレクションの中から、条件に合った要素を引っ張ってくるメソッド。
a, b, cという3つの文字列から成るコレクションがあったとして、cとdを取り出しているのが作例。
コレクションの中から一つだけ要素を取り出したいというシーンは多く、Selectと並んでよく使うメソッド。
良く似たメソッドにFirstとSingleがあるけれど、Firstは要素が見つからなかったときに例外を投げ、Singleは全要素を調べる(FirstOrDefaultは一つでも要素が見つかればそこで探索をやめる)ため、ほとんど使わない。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
// FirstOrDefault var texts = new[] { "a", "b", "c" }; var searchedTextOfD = texts.FirstOrDefault(text => text == "d"); var dExist = searchedTextOfD != null; // Does D exist? : False Console.WriteLine("Does D exist? : " + dExist.ToString()); var searchedTextOfA = texts.FirstOrDefault(text => text == "a"); var aExist = searchedTextOfA != null; // Does A exist? : True Console.WriteLine("Does A exist? : " + aExist.ToString()); |
Hello LINQ world!
一先ずはこの四種の神器を使いこなし、必要に応じて他のLINQメソッドに手を伸ばしていこう。
LINQに慣れるとC#を書くのが本当に楽しくなる。冗談じゃなくマジで、メソッドチェーンのドットを一つ打つ度にドーパミンが出てると思う。それぐらいヤバイ代物。
C#おすすめ図書
他の言語をやったことがあって、その言語の作法でC#を書いちゃったことのある人へ
メンテナンス性が高く、チームメンバーにとって読みやすいコードを書くための永遠の名著
2 Responses
[C# .Net] ちょっと上行くC#erになるためのLINQの使い方。 | TOACH
[…] Hello LINQ world. 野暮ったいC#コードから卒業したいアナタへ。LINQ 基本の4つ。 […]
[C# .Net] SelectとSelectManyの使い分け。そしてforeachでインデックスを使う方法。 | TOACH
[…] Hello LINQ world. 野暮ったいC#コードから卒業したいアナタへ。LINQ 基本の4つ。 […]