LINQ クエリの基本操作 (C#)
ここでは、LINQ のクエリ式およびクエリで実行する一般的な操作について簡単に紹介します。 詳細については、次のトピックを参照してください。
注意
SQL や XQuery などのクエリ言語に既に精通している場合は、このトピックの大部分をスキップできます。LINQ のクエリ式における句の順序について理解するには、次のセクションの from 句に関するトピックを参照してください。
データ ソースの取得
LINQ クエリに必要な最初の手順は、データ ソースを指定することです。 ほとんどのプログラミング言語と同様に、C# でも、変数は使用する前に宣言しておく必要があります。 LINQ クエリでは、データ ソース (customers) と範囲変数 (cust) を定義するために from 句が最初に使用されます。
//queryAllCustomers is an IEnumerable<Customer>
var queryAllCustomers = from cust in customers
select cust;
範囲変数は foreach ループの反復変数に似ていますが、クエリ式で実際の反復が発生しない点が異なります。 クエリが実行されると、範囲変数は customers の連続する各要素への参照として機能します。 cust の型はコンパイラで推論できるので、明示的に指定する必要はありません。 追加の範囲変数は let 句で定義できます。 詳細については、「let 句 (C# リファレンス)」を参照してください。
注意
ArrayList などの非ジェネリック データ ソースの場合は、範囲変数を明示的に型指定する必要があります。詳細については、「方法 : LINQ を使用して ArrayList を照会する」および「from 句 (C# リファレンス)」を参照してください。
フィルター処理
おそらく、最も一般的なクエリ操作は、ブール式の形式でフィルターを適用することです。 フィルターにより、式が true になる要素だけがクエリから返されます。 結果は where 句を使用して生成されます。 フィルターは、基本的に、ソース シーケンスから除外する要素を指定します。 次の例では、住所がロンドンにある customers だけが返されます。
var queryLondonCustomers = from cust in customers
where cust.City == "London"
select cust;
使い慣れた C# の論理 AND 演算子と論理 OR 演算子を使用すると、必要に応じていくつでも where 句にフィルター式を適用できます。 たとえば、住所が "ロンドン" にあり、かつ (AND) 名前が "Devon" の顧客だけを返すには、次のコードを記述します。
where cust.City=="London" && cust.Name == "Devon"
住所がロンドンまたはパリにある顧客を返すには、次のコードを記述します。
where cust.City == "London" || cust.City == "Paris"
詳細については、「where 句 (C# リファレンス)」を参照してください。
順序付け
返されるデータを並べ替えると便利な場合がよくあります。 orderby 句は、返されるシーケンス内の要素を、並べ替える型の既定の比較子に従って並べ替えます。 たとえば、次のクエリは、Name プロパティに基づいて結果を並べ替えるように拡張できます。 Name は文字列なので、既定の比較子によってアルファベット順 (A ~ Z) に並べ替えられます。
var queryLondonCustomers3 =
from cust in customers
where cust.City == "London"
orderby cust.Name ascending
select cust;
結果を逆の順序 (Z ~ A) で並べ替えるには、orderby…descending 句を使用します。
詳細については、「orderby 句 (C# リファレンス)」を参照してください。
グループ化
group 句を使用すると、指定したキーに基づいて結果をグループ化できます。 たとえば、結果を City 別にグループ化して、住所がロンドンまたはパリにあるすべての顧客を別々のグループに分けることができます。 この場合のキーは cust.City です。
// queryCustomersByCity is an IEnumerable<IGrouping<string, Customer>>
var queryCustomersByCity =
from cust in customers
group cust by cust.City;
// customerGroup is an IGrouping<string, Customer>
foreach (var customerGroup in queryCustomersByCity)
{
Console.WriteLine(customerGroup.Key);
foreach (Customer customer in customerGroup)
{
Console.WriteLine(" {0}", customer.Name);
}
}
group 句でクエリを終了すると、結果はリストのリストという形式になります。 リストの各要素はオブジェクトであり、このオブジェクトには、Key メンバーと、そのキーに基づいてグループ化された要素のリストが含まれます。 グループのシーケンスを生成するクエリを反復処理する場合は、入れ子になった foreach ループを使用する必要があります。 外側のループで各グループを反復処理し、内側のループで各グループのメンバーを反復処理します。
グループ操作の結果を参照する必要がある場合は、into キーワードを使用して、さらに照会が可能な識別子を作成できます。 次のクエリでは、顧客が 2 人よりも多いグループだけが返されます。
// custQuery is an IEnumerable<IGrouping<string, Customer>>
var custQuery =
from cust in customers
group cust by cust.City into custGroup
where custGroup.Count() > 2
orderby custGroup.Key
select custGroup;
詳細については、「group 句 (C# リファレンス)」を参照してください。
結合
結合操作は、データ ソースで明示的にモデル化されていないシーケンス間に関連付けを作成します。 たとえば、場所が同じであるすべての顧客と販売業者を検索するには、結合を実行できます。 LINQ では、join 句はデータベース テーブルを直接操作するのではなく、常にオブジェクト コレクションに対して動作します。
var innerJoinQuery =
from cust in customers
join dist in distributors on cust.City equals dist.City
select new { CustomerName = cust.Name, DistributorName = dist.Name };
LINQ では、SQL ほど頻繁に join を使う必要はありません。これは、LINQ の外部キーが、オブジェクト モデルでは項目のコレクションを保持するプロパティとして表されるためです。 たとえば、Customer オブジェクトには Order オブジェクトのコレクションが含まれます。 結合を実行しなくても、ドット表記を使用して注文にアクセスできます。
from order in Customer.Orders...
詳細については、「join 句 (C# リファレンス)」を参照してください。
選択 (投影)
select 句は、クエリの結果を生成し、返された各要素の "シェイプ" つまり型を指定します。 たとえば、完全な Customer オブジェクト、1 つのメンバーのみ、メンバーのサブセット、計算や新しいオブジェクトの作成に基づいたまったく異なる結果の種類のいずれから結果が構成されるかを指定できます。 select 句がソース要素のコピー以外を生成する場合、その操作は投影と呼ばれます。 投影を使用したデータの変換は、LINQ のクエリ式の強力な機能です。 詳細については、「LINQ によるデータ変換 (C#)」および「select 句 (C# リファレンス)」を参照してください。