読者です 読者をやめる 読者になる 読者になる

LINQ教の簡単な布教

この記事はKMCアドベントカレンダー
の3日目の記事です。
どうもこんにちは。KMCの会表(会長と代表の狭間の生物)lastcatです*1。僕は技術的には他の執筆者と比べると雑草レベルですが、まぁいい機会と思って恥を晒すことにします。
この記事はC#のステキ機能LINQについてです。
さて、LINQがどういうモノか、ということを文章で説明することにあんまり、意味を感じないので、どんどん実例をあげていきながら徐

々に馴染んでいこうと思います。なお今回取り上げるのは一番普遍的であると思っているLINQtoObjectのみなことにご注意ください。

まず簡単な話

int[] array = {1,2,4,3,4}
という簡単な配列に対して、「偶数である要素だけを表示する」という処理を書くことを考えてみます。

//単純なfor
for(int i = 0; i < array.Length; i++)
{
	if(array[i]%2==0)
	Console.WriteLine(array[i]);
}
//foreach
foreach(int e in array)
{
	if(e%2==0)
	Console.WriteLine(e);
}

となりますね。これをLINQを使って書くと、

var q = from e in array where e%2==0 select e;
foreach(int i in q)
{
	Console.WriteLine(i);
}

となります。
別のメソッド形式で書けば、

foreach(int e in array.Where(e => e%2==0))
{
	Console.WriteLine(e);
}

となります。
クエリ式はIEnumerableを受け取ってIEnumerableを返すので、リンク式を連結することもできます。これは再利用性があっていいですね。

var q = from e in array where e%2==0 select e;
var q2 = from e in q where e >= 65 select e;

意図としてはクエリ式表記のほうがわかりやすく、MSDN(http://msdn.microsoft.com/ja-jp/library/bb397676.aspx)でも『一般に、LINQ クエリを記述する場合、可能なときは常にクエリ構文を使用し、必要に応じてメソッド構文を使用することをお勧めします。 この 2つの形式の間に意味および動作についての違いはありません。 クエリ式は多くの場合、メソッド構文で記述された同等の式に比べてわかりやすくなります。』とあります。ですが、クエリ操作について、クエリ式表記はメソッド式表記のほとんど部分集合なので慣れればそちらのほうが表現力は上がるとおもわれます。

だんだん話があやしくなってくる

既にある配列やリストなどに対してLINQが有効に働くのはわかっていただけたと思います。でも、それだけではありません。ToArrayメソッドやToListメソッドを使えば、やはりループを回すことなく中身の詰まった配列やリストを生成することができます。

int[] array = Enumerable.Range(0, 100).ToArray();

EnumerbaleはIEnumerableを実装するオブジェクトをクエリするためのstaticメソッドが集まったクラスです。そしてRangeメソッドは連続した整数のシーケンスを返すメソッドです。最後のToArrayメソッドはもうわかりますね。

つまりLINQで配列などのコレクションを生成しLINQで処理することによって、コード内のループをかなり駆逐することができます。

//0から100までの整数の中で7で割ったときに4余る数の中で二乗して初めて500を超える数を出力
Console.WriteLine(Enumerable.Range(0, 100).Where(e => e % 7 == 4).Select(e => e * e).First(e => e > 500));
//ちなみに、何も考えずに書くと、
for (int i = 0; i <= 100; i*=i)
{
	if(i%7==4 && i*i > 500)
	{
		Console.WriteLine(i * i);
		break;
	}
}

こんな感じでしょうか。LINQを使わないとちょっとしたことでも結構面積を取っててやらしい感じですね(そんなことはない)。

ひよったまとめ

LINQは慣れている人とそうでない人でかなり可読性が変わるため、誰かと共同でコードを書くプロジェクトにいきなり導入するとかはちょっと危ないかもしれません。でも慣れればかなり直観的に意図を表現できるため、まだ触れたことない人は、自分のコードの中のforを置き換えてみるみたいなことをしながらちょこちょこ親しんでいくのはいかがでしょうか。

次回はid:tyageによる「部誌の予告編か番外編でも(ただの旅行記になりそう)」です。KMCでは旅行記のハードルが一部の特徴的な部員のせいでかなり上がってる気がするのですが、いやはやどうなることやら。
それでは明日もお楽しみに。

*1:KMCでは会長は翌年の代表を務めることになっています