クエリ式
クエリ式では、SQL または XQuery に似た宣言構文を使用して、 System.Collections.Generic.IEnumerable<T> コレクションに対してクエリを実行します。 コンパイル時に、クエリ構文は、LINQ プロバイダーの標準クエリ メソッドの実装に対するメソッド呼び出しに変換されます。 アプリケーションは、 using
ディレクティブを使用して適切な名前空間を指定することで、スコープ内の標準クエリ演算子を制御します。 次のクエリ式は、文字列の配列を受け取り、文字列の最初の文字に従ってグループ化し、グループを並べ替えます。
var query = from str in stringArray
group str by str[0] into stringGroup
orderby stringGroup.Key
select stringGroup;
暗黙的に型指定された変数 (var)
次に示すように、 var 修飾子を使用して、型を推論して割り当てるようにコンパイラに指示できます。
var number = 5;
var name = "Virginia";
var query = from str in stringArray
where str[0] == 'm'
select str;
var
として宣言された変数は、明示的に指定した型の変数と同様に、厳密に型指定されます。
var
を使用すると、ローカル変数に対してのみ匿名型を作成できます。 詳細については、「 暗黙的に型指定されたローカル変数」を参照してください。
オブジェクト初期化子とコレクション初期化子
オブジェクト初期化子とコレクション初期化子を使用すると、オブジェクトのコンストラクターを明示的に呼び出さずにオブジェクトを初期化できます。 初期化子は、通常、ソース データを新しいデータ型に投影するときに、クエリ式で使用されます。 パブリック Customer
プロパティとName
プロパティを持つ Phone
という名前のクラスを想定すると、オブジェクト初期化子は次のコードのように使用できます。
var cust = new Customer { Name = "Mike", Phone = "555-1212" };
Customer
クラスを続けて、IncomingOrders
というデータ ソースがあり、OrderSize
が大きい注文ごとに、その順序に基づいて新しいCustomer
を作成するとします。 LINQ クエリは、このデータ ソースで実行し、オブジェクトの初期化を使用してコレクションを埋めることができます。
var newLargeOrderCustomers = from o in IncomingOrders
where o.OrderSize > 5
select new Customer { Name = o.Name, Phone = o.Phone };
データ ソースには、Customer
などのOrderSize
クラスよりも多くのプロパティが定義されている場合がありますが、オブジェクトの初期化では、クエリから返されるデータは目的のデータ型に成形されます。クラスに関連するデータを選択します。 その結果として、必要とする新しい System.Collections.Generic.IEnumerable<T> が Customer
に入力されました。 前の例は、LINQ のメソッド構文でも記述できます。
var newLargeOrderCustomers = IncomingOrders.Where(x => x.OrderSize > 5).Select(y => new Customer { Name = y.Name, Phone = y.Phone });
C# 12 以降では、 コレクション式 を使用してコレクションを初期化できます。
詳細については、以下を参照してください。
匿名型
コンパイラは 匿名型を構築します。 型名はコンパイラでのみ使用できます。 匿名型を使用すると、個別の名前付き型を定義しなくても、クエリ結果で一連のプロパティを一時的にグループ化する便利な方法が提供されます。 匿名型は、次に示すように、新しい式とオブジェクト初期化子で初期化されます。
select new {name = cust.Name, phone = cust.Phone};
C# 7 以降では、 タプルを 使用して名前のない型を作成できます。
拡張メソッド
拡張メソッドは、型のインスタンス メソッドであるかのように呼び出すことができるように、型に関連付けることができる静的メソッドです。 この機能を使用すると、実際に新しいメソッドを実際に変更することなく、既存の型に新しいメソッドを "追加" できます。 標準クエリ演算子は、 IEnumerable<T>を実装する任意の型に LINQ クエリ機能を提供する拡張メソッドのセットです。
ラムダ式
ラムダ式は、=>
演算子を使用して入力パラメーターを関数本体から分離するインライン関数であり、コンパイル時にデリゲートまたは式ツリーに変換できます。 LINQ プログラミングでは、標準のクエリ演算子に直接メソッド呼び出しを行うと、ラムダ式が発生します。
データとしての式
クエリ オブジェクトは構成可能です。つまり、メソッドからクエリを返すことができます。 クエリを表すオブジェクトは、結果のコレクションを格納するのではなく、必要に応じた結果を生成する手順を格納します。 メソッドからクエリ オブジェクトを返す利点は、さらに構成または変更できることです。 したがって、クエリを返すメソッドの戻り値または out
パラメーターにも、その型が必要です。 メソッドは、クエリを具象 List<T> または Array 型に具体化した場合、クエリ自体ではなくクエリ結果を返します。 メソッドから返されるクエリ変数は、引き続き構成または変更できます。
次の例では、最初のメソッド QueryMethod1
は戻り値としてクエリを返し、2 番目のメソッド QueryMethod2
はクエリを out
パラメーターとして返します (例ではreturnQ
)。 どちらの場合も、クエリ結果ではなく、返されるクエリです。
IEnumerable<string> QueryMethod1(int[] ints) =>
from i in ints
where i > 4
select i.ToString();
void QueryMethod2(int[] ints, out IEnumerable<string> returnQ) =>
returnQ = from i in ints
where i < 4
select i.ToString();
int[] nums = [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ];
var myQuery1 = QueryMethod1(nums);
クエリ myQuery1
は、次の foreach ループで実行されます。
foreach (var s in myQuery1)
{
Console.WriteLine(s);
}
マウス ポインターを myQuery1
の上に置き、その種類を確認します。
QueryMethod1
を使用せずに、myQuery1
から返されたクエリを直接実行することもできます。
foreach (var s in QueryMethod1(nums))
{
Console.WriteLine(s);
}
QueryMethod1
の呼び出しの上にマウス ポインターを置き、戻り値の型を確認します。
QueryMethod2
は、 out
パラメーターの値としてクエリを返します。
QueryMethod2(nums, out IEnumerable<string> myQuery2);
// Execute the returned query.
foreach (var s in myQuery2)
{
Console.WriteLine(s);
}
クエリの構成を使用して、クエリを変更できます。 この場合、前のクエリ オブジェクトを使用して新しいクエリ オブジェクトを作成します。 この新しいオブジェクトは、元のクエリ オブジェクトとは異なる結果を返します。
myQuery1 = from item in myQuery1
orderby item descending
select item;
// Execute the modified query.
Console.WriteLine("\nResults of executing modified myQuery1:");
foreach (var s in myQuery1)
{
Console.WriteLine(s);
}
.NET