Posted at

【小ネタ】LINQの「遅延評価」「即時評価」って何が違うの?


最初に

本記事は「Effective C#」で得た知見である、「即時評価」「遅延評価」について確認したものとなります。

何番煎じとか知らない。備忘録として書いておきます。

LINQを知っている前提で解説します。


遅延評価

さて、クエリを定義した段階ではまだ、「このクエリを走査した場合に実行される一連の手順」を明記しただけとなります。なので、クエリの結果としてもたらされるシーケンスは走査時点でのデータに依存しています。つまり走査の度に新しい結果が得られると言うことです。

必要になった要素から、必要になった分だけ、必要になった時に計算する方法を「遅延評価(lazy evaluation)」と呼びます。


遅延評価の性質を利用

遅延評価の性質を利用して既存のクエリ式に別のクエリ式を付け足すようなこともできます。

例えば

var seq1 = Crete(5, () => DataTime. Now);

に対して

var seq2 = from val in seq1 (以降なんか処理);

seq2はsep1の返却値を弄るのではなく、あくまでも、seq1に対しての付け足し式となります。このことから、seq1はクエリによって作成された変数を保持しているわけではなく、式ツリーを保持していることがわかります。


遅延評価のメリット


  • 省メモリ

  • 無限ループにも対応可能

  • 返ってきた値を逐次反映させる事ができる

基本的にはクエリに対しては遅延評価を行うのが最善であると考えられています。


即時評価

ただし、場合によってはある時点における一連の値を一度に今すぐ受け取りたい場合があります。

その場合には「即時評価(eager evaluation)」を用います。

ToList()ToArray()を用いることで強制的にクエリを実行し、結果を即座に作成してキャッシュすることができます。もちろん、作成後は後から参照することも可能です。

ほとんどの場合で、即時評価よりも遅延評価を行った方が作業量もメモリも少なく済みます

1回以上走査するクエリがある場合、どちらの挙動が必要かよく考えましょう。


参考