Effective C# 3rd 読書メモ 37 クエリの遅延評価を使う

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();
}

注意が必要なのは、クエリの演算によっては、一連の要素の全体が必要になることもある、ということだ。OrderByMaxMinはいずれも遅延評価できない演算である。

一方、特定の時点の一連の要素のスナップショットが欲しい場合もある。その際は、ToList()ないしToArray()を実行して、結果を取得すればよい。

一連の要素を処理する際は、以下のような事項に気をつける。

  • データの取得タイミングを遅らせ、コピーを減らす(無駄にToList()ToArray()を使わない)
  • Whereによるフィルタリングを行う場合、全体を必要とする演算より前で実行する
  • 膨大な数の要素を一部のみを取得する際は、全体に対する演算が実行されないようにする

コメントを残す

コメントを残す