LINQ

LINQとは

C#3.0からLINQというものが導入されました。
LINQは一言で言えば文法の拡張で、コレクション(データの集合)に対する操作を拡張するものです。
従来は数行必要だった処理を一行で簡潔に書けるようになります。
(コレクション=ListクラスDictionaryクラスなど、データをまとめて扱うもの)

LINQにはメソッド構文クエリ構文の二通りの書き方があります。
メソッド構文は従来のC#的なコードとほぼ同じ形式で、データの集合に対して便利なメソッドが多数提供されているイメージです。
クエリ構文はデータベース言語であるSQLに近い構文となっています。

まずはメソッド構文についての説明から行います。

より正確に言えば、LINQは様々なデータソースに共通の方法で操作する方法を提供するものです。
データソースとはプログラミングコード上の変数(配列)のほか、外部のデータベースやXMLなどです。
従来はそれぞれで異なるコードを記述していたものを、共通の記法で読み書きをできるようにしたものがLINQです。

このサイトではそこまで突っ込んだ方法までは扱わないので、「何か便利なメソッドがたくさんある」という認識で問題ありません。

usingディレクティブ

LINQを使用するにはコードの先頭にusing System.Linq;が必要です。
もしなければ追加してください。


using System;
using System.Collections.Generic;
using System.Linq;
//↑なければ追加

.NET6.0以降なら暗黙的なusingディレクティブにより自動的に追加されていると思います。

シーケンス

LINQでは「コレクション(データの集合)」に対して操作をすると説明しましたが、LINQ的にはこれをシーケンスと呼びます。
シーケンスとは「要素を順番に取り出すことができるもの」「順に並んだ列」という意味で、配列やListなどがそれにあたります。

LINQの例

LINQの機能のひとつ、Whereメソッドを使用してListの要素から偶数を取り出してみます。


List<int> nums = new List<int>()
{
    1, 2, 5, 9, 11, 14, 18, 21
};

//偶数を取り出す
IEnumerable<int> evens = nums.Where(n => n % 2 == 0);

foreach (var n in evens)
    Console.Write("{0} ", n);
2 14 18 

LINQ拡張メソッドの呼び出し方法は、通常の(Listクラスなどが提供する)メソッドと全く同じです。
Whereメソッドは指定のシーケンス(今回はnums)から条件に合う要素をすべて返します。

条件式には通常はラムダ式を使用します。
この例では

  1. numsから要素をひとつ取り出しnに格納
  2. その要素が2で割り切れるか否かを判定
  3. 割り切れるなら新しい(戻り値となる)シーケンスに追加
  4. 1~3をすべてのnums要素に対して実行
  5. 最後に3のシーケンスを戻り値として返す

という処理を行っています。

IEnumerable型

LINQメソッドの多くはIEnumerable<データ型>という型を返すものが多くあり、 Whereメソッドもそのひとつです。
IEnumerable型はインターフェイスで、ListクラスやDictionaryクラスなどのLINQを使用できるデータ型はすべてIEnumerableインターフェイスを継承して作られています。
インターフェイスはメソッドの定義(オーバーロード)を強制するので、異なるクラスであってもIEnumerable型を継承するクラスであれば共通のメソッドが使用できることが保証されています。

List、配列に変換

IEnumerable<int>型のままでもforeach文で値を取り出すことはできますが、添え字(インデクサ)で各要素にアクセスできません。
IEnumerable型をListクラスに変換する場合はToListメソッドを使用します。
配列に変換する場合はToArrayメソッドを使用します。


List<int> evenList =
    nums.Where(n => n % 2 == 0).ToList();
int[] evenArray = 
    nums.Where(n => n % 2 == 0).ToArray();

//ただのListなので
//添え字でアクセス可能
evenList[0] = 4;

ただし、IEnumerable型は可能ならばそのまま扱った方が高速に動作する可能性があります。
(Listや配列に変換するコストもかかります)


LINQのその他のメソッドは次ページで解説します。
数が多いですが、すべて覚える必要はなく必要に応じて調べると良いです。