林克后期约束混乱

mch*_*ago 3 c# linq

有人可以解释一下我在这里缺少什么.基于我的基本理解,将在使用结果时计算linq结果,我可以在下面的代码中看到.

 static void Main(string[] args)
 {
     Action<IEnumerable<int>> print = (x) =>
     {
         foreach (int i in x)
         {
             Console.WriteLine(i);
         }
     };

     int[] arr = { 1, 2, 3, 4, 5 };
     int cutoff = 1;
     IEnumerable<int> result = arr.Where(x => x < cutoff);
     Console.WriteLine("First Print");
     cutoff = 3;
     print(result);
     Console.WriteLine("Second Print");
     cutoff = 4;
     print(result);
     Console.Read();
}
Run Code Online (Sandbox Code Playgroud)

输出:

First Print
1
2
Second Print
1
2
3

现在我改变了

arr.Where(x => x < cutoff); 
Run Code Online (Sandbox Code Playgroud)

IEnumerable<int> result = arr.Take(cutoff); 
Run Code Online (Sandbox Code Playgroud)

输出如下.

First Print
1
Second Print
1

为什么使用Take,它不使用变量的当前值?

Jar*_*Par 6

您看到的行为来自评估LINQ函数的参数的不同方式.该Where方法接收lambda,该lambda cutoff通过引用捕获值.它是按需评估的,因此可以看到当时的价值cutoff.

Take方法(以及类似的方法Skip)采用int参数,因此cutoff通过值传递.使用的值是的值cutoff的时刻的Take方法被调用,而不是当该查询求值

注意:这里的后期绑定这个术语有点不正确.后期绑定通常是指在运行时与编译时确定表达式绑定的成员的过程.在C#中你可以用dynamic或反思来完成这个.LINQ按需评估其部件的行为称为延迟执行.