LINQ クエリの基本操作 (C#)

このトピックでは、LINQ クエリ式とクエリで実行する一般的な操作について、簡単に説明します。 詳細については、以下のトピックを参照してください。

LINQ クエリ式

標準クエリ演算子の概要 (C#)

チュートリアル: C# でのクエリの作成

注意

既に 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 句」をご覧ください。

注意

ArrayList などの非ジェネリック データ ソースの場合は、範囲変数を明示的に型指定する必要があります。 詳細については、「LINQ を使用して ArrayList にクエリを実行する方法 (C#)」および「from 句」を参照してください。

フィルター処理

最も一般的なクエリ操作は、ブール式の形式でフィルターを適用することです。 クエリにフィルターを使用すると、式の条件に該当する要素だけがクエリから返されます。 結果は、where 句を使って生成されます。 フィルターは、実質的にはソース シーケンスから除外する要素を指定します。 次の例では、住所がロンドンにある customers だけが返されます。

var queryLondonCustomers = from cust in customers
                           where cust.City == "London"
                           select cust;

使い慣れた C# 論理 AND 演算子と論理 OR 演算子を使用すると、必要なだけのフィルター式を where 句に適用できます。 たとえば、住所が "London" にあり、かつ (AND) 名前が "Devon" の顧客だけを返すには、次のコードを記述します。

where cust.City == "London" && cust.Name == "Devon"

住所がロンドンまたはパリにある顧客を返すには、次のコードを記述します。

where cust.City == "London" || cust.City == "Paris"

詳しくは、「where 句」をご覧ください。

順序

返されたデータを並べ替えると便利なことがよくあります。 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 句」を参照してください。

グループ化

指定したキーに基づいて結果をグループ化するには、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 句」をご覧ください。

結合

結合操作は、データ ソースで明示的にモデル化されていないシーケンス間に関連付けを作成します。 たとえば、結合を実行して、住所地が同じすべての顧客と販売業者を検索することができます。 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 句」を参照してください。

選択 (投影)

select 句はクエリの結果を生成し、返される各要素の "シェイプ" つまり型を指定します。 たとえば、完全な Customer オブジェクト、1 つのメンバーのみ、メンバーのサブセット、または計算や新しいオブジェクトの作成に基づいた、まったく異なる種類の結果のいずれで結果が構成されるかを指定できます。 select 句でソース要素のコピー以外のものを生成する場合、その操作は投影と呼ばれます。 投影を使用したデータの変換は、LINQ クエリ式の強力な機能です。 詳細については、「LINQ によるデータ変換 (C#)」と「select 句」を参照してください。

関連項目