LINQとは、さまざまなデータソースを共通の方法で処理できる仕組みです。
データソース | 技術 | 参照 |
---|---|---|
オブジェクト (.NETコレクション、ファイル、文字列など) | LINQ to Objects | |
データセット (DataSet) | LINQ to DataSet | |
SQL Server | LINQ to SQL (DLINQ) |
|
エンティティ (Entity Framework : EF) を介した、リレーショナル データベース。データ プロバイダが提供されているならば、SQL Server以外にも対応 | LINQ to Entities | |
メモリ内のXML文書 (XML documents) | LINQ to XML (XLINQ) |
int[] values = { 1, 2, 3, 4, 5 };
IEnumerable<int> query =
from a in values
where a > 3
select a;
foreach (int variable in query)
{
Console.Write(variable); // 4, 5
}
C# の統合言語クエリ (LINQ) | Microsoft Learn
句 (clause) | 用途 |
---|---|
from | クエリを実行するデータソース。またはローカルの範囲変数 |
where | 結果のフィルタ |
select | 結果の型と形状 |
group | 結果のグループ化 |
orderby | 結果の並べ替え |
join | 2つのデータソースを結合 |
into | select、group、joinの結果を参照するための識別子 |
let | クエリ式の結果を格納 |
クエリ式はfrom句で始め、groupまたはselect句で終えます。
クエリまたはサブクエリを実行するデータソース、またはソース シーケンスの各要素を表すローカルの範囲変数を指定します。from 句 - C# リファレンス | Microsoft Learn
from 範囲変数 in データソース
データソースはIEnumerable、IEnumerable<T>またはIQueryable<T>の派生型である必要があります。
データソースがList<int>ならば範囲変数 (range variable) はintと推定されますが、ArrayListのような非ジェネリックの型の場合、型を指定してキャストさせる必要があります。LINQ を使用して ArrayList にクエリを実行する方法 (C#) | Microsoft Learn
ArrayList arrayList = new ArrayList { 1, 2, 3 }; IEnumerable<int> query1 = from num in arrayList // error CS1934: ソース型 'ArrayList' のクエリ パターンの実装が見つかりませんでした。'Select' が見つかりません。範囲変数 'a' の型を明示的に指定してください。 select num; IEnumerable<int> query2 = from int num in arrayList // ok select num;
データソースがIEnumerableのときは、すべての要素がIEnumerable<T>へキャストされた上で処理されます。
どの要素がクエリ式から返されるかを指定します。where 句 - C# リファレンス | Microsoft Learn
記述する内容 | 例 |
---|---|
単一の述語 (predicate) を記述 | where num < 5 |
&&や||演算子を使用して、複数の述語を記述 | where num < 5 && num % 2 == 0 |
演算子を省略して、複数の述語を記述 (&&演算子を指定したと見なされる) | where num < 5 where num % 2 == 0 |
メソッドを記述 | where IsEven(num) |
whereキーワードは、コンパイル時にWhere()メソッドの呼び出しに変換されます。また記述した式は、クエリの結果を要求されたときに評価されます。
クエリが実行されたときに生成される値の、型を指定します。
select 句 - C# リファレンス - C# | Microsoft Learn
int[] values = { 0x61, 0x62, 0x63 };
IEnumerable<char> query =
from num in values
select (char)num;
query.ToArray(); // 'a', 'b', 'c'
string[] words = { "B1", "A1", "A2", "B2" }; IEnumerable<IGrouping<char, string>> query = from word in words group word by word[0]; Dictionary<char, int> dic = query.ToDictionary(s => s.Key, s => s.Count()); // {[B, 2]} // {[A, 2]}
グループに追加の操作をするならば、intoで一時的な識別子を作成しクエリを続け、selectまたは別のgroup句で終了します。
IEnumerable<IGrouping<char, string>> query = from word in words group word by word[0] into c orderby c.Key select c;
複数のキーで要素をグループ化するには、複合キー (composite keys) を用います。複合キーでグループ化する - group 句 - C# リファレンス - C# | Microsoft Learn
string[] words = { "B1", "A1", "A2", "B2", "B30" }; var query = from word in words group word by new { c = word[0], length = word.Length }; var dic = query.ToDictionary(s => s.Key, s => s.Count()); // {[{ c = B, length = 2 }, 2]} // {[{ c = A, length = 2 }, 2]} // {[{ c = B, length = 3 }, 1]}
このときの複合キーを匿名型 (anonymous type) ではなく名前付きの型 (named type) とするには、キーとなる構造体を
struct MyStruct { public char c; public int length; }
のように定義して
IEnumerable<IGrouping<MyStruct, string>> query = from word in words group word by new MyStruct { c = word[0], length = word.Length };
のように利用します。このとき構造体ではなくクラスとするには、Equals()とGetHashCode()をオーバーライドして定義します。
class MyClass { public char c; public int length; public override bool Equals(object obj) { MyClass other = (MyClass)obj; return other.c == this.c && other.length == this.length; } public override int GetHashCode() { string str = $"{this.c}{this.length}"; return str.GetHashCode(); } }ディレクトリ ツリーで重複するファイルを照会する方法 (LINQ) (C#) - C# | Microsoft Learn
返されるシーケンスまたはサブシーケンス (グループ) を、昇順または降順で並べ替えられます。orderby 句 - C# リファレンス | Microsoft Learn
クエリ構文 | メソッド構文 | 機能 |
---|---|---|
orderby | OrderBy() | 要素を、昇順に並べ替える |
orderby … descending | OrderByDescending() | 要素を、降順に並べ替える |
orderby …, … | ThenBy() | 後続の要素を、昇順に並べ替える |
orderby …, … descending | ThenByDescending() | 後続の要素を、降順に並べ替える |
なし | Reverse() | 要素の順序を反転させる |
string[] words = { "B", "A", "D1", "C1" }; IEnumerable<string> query1 = from word in words orderby word.Length select word; // "B", "A", "D1", "C1" IEnumerable<string> query2 = from word in words orderby word[0] descending select word; // "D1", "C1", "B", "A" IEnumerable<string> query3 = from word in words orderby word.Length, word[0] select word; // "A", "B", "C1", "D1"
直接の関連のない異なるソース シーケンスの要素を関連付けられます。join 句 - C# リファレンス | Microsoft Learn
結合方法 | 機能 |
---|---|
内部結合 (Inner join) | |
グループ結合 (Group join) | 結果を配列に格納 |
左外部結合 (Left outer join) | 一致する要素がないときに、既定の要素を格納 |
join句の後にintoがなければJoin()に、あればGroupJoin()に変換されます。
LINQではクエリの結果ではなく、クエリを格納する変数をクエリ変数と呼びます。クエリ変数 - クエリ式の基本 (C# での LINQ) | Microsoft Learn
クエリを用いたクエリ構文は、コンパイル時にメソッド構文に変換されます。
句 | クエリの例 | 対応するメソッド |
---|---|---|
from | from int i in numbers | Cast() |
from | 複数のfrom句 | SelectMany |
where | where | Where() |
select | select | Select() |
group |
|
GroupBy() |
orderby | orderby | OrderBy() |
orderby | orderby … descending | OrderByDescending() |
orderby | orderby …, … | ThenBy() |
orderby | orderby …, … descending | ThenByDescending() |
join | join … in … on … equals … into … | GroupJoin() |
join | join … in … on … equals … | Join() |
int[] values = { 1, 2, 3, 4, 5 }; // クエリ構文 IEnumerable<int> query1 = from num in values where num > 3 select num; // メソッド構文 IEnumerable<int> query2 = values.Cast<int>() .Where(a => a > 3) .Select(a => a);
Count()やMax()などにはクエリ式の句がないため、メソッドを用いる必要があります。
データを評価するごとに呼び出される式で処理数を計数することで、処理の進捗を示せます。
int count = 0;
IEnumerable<int> source = Enumerable.Range(0, 10);
IEnumerable<int> query = source.Where((x) =>
{
Console.WriteLine(count++); // 処理数を数える
return x % 2 == 0;
});
query.ToArray();