Linq: Select と Take の組み合わせ

xs.Select(処理).Take(N)xs.Take(N).Select(処理) に違いがあるか気になりました。 つまり、欲しい値は N 個だけなんだけど、Select(処理) は xs の全ての要素に対して適用されるのだろうか。

using System;
using System.Linq;

class Program {
    static int Identity(int val) {
        Console.WriteLine("val: {0}", val);
        return val;
    }

    static void Main() {
        var xs = new[] { 1, 2, 3, 4, 5 };

        var ret = xs.Select(Identity).Take(3);
        Console.WriteLine(string.Join(" ", ret));
    }
}

実行結果です。

val: 1
val: 2
val: 3
1 2 3

上の結果を見ると、Select() による評価は、Take() で必要とする個数分しか評価していないことが分かりました。よって、xs.Select(処理).Take(N)xs.Take(N).Select(処理) は、本質的な違いはなさそうです。