LINQによって定義したクエリは、通常は遅延評価(lazy evaluation)され、データは実際に必要になるまで取得されない。しかし、すぐに取得する(eager evaluation)こともできる。
実際に遅延評価の動作を確認するには、以下のようなコードが使用できる。
public static void Main()
{
WriteLine($"Start time for Test One: {DateTime.Now:T}");
var sequence = Generate(10, () => DateTime.Now);
WriteLine("Waiting...");
Thread.Sleep(millisecondsTimeout: 1000);
WriteLine("Iterating...");
foreach (var value in sequence)
WriteLine($"{value:T}");
WriteLine("Waiting...");
Thread.Sleep(millisecondsTimeout: 1000);
WriteLine("Iterating...");
foreach (var value in sequence)
WriteLine($"{value:T}");
}
private static IEnumerable<TResult>
Generate<TResult>(int number, Func<TResult> generator)
{
for (var i = 0; i < number; i++)
yield return generator();
}
注意が必要なのは、クエリの演算によっては、一連の要素の全体が必要になることもある、ということだ。OrderBy
、Max
、Min
はいずれも遅延評価できない演算である。
一方、特定の時点の一連の要素のスナップショットが欲しい場合もある。その際は、ToList()
ないしToArray()
を実行して、結果を取得すればよい。
一連の要素を処理する際は、以下のような事項に気をつける。
- データの取得タイミングを遅らせ、コピーを減らす(無駄に
ToList()
やToArray()
を使わない) Where
によるフィルタリングを行う場合、全体を必要とする演算より前で実行する- 膨大な数の要素を一部のみを取得する際は、全体に対する演算が実行されないようにする