C# 使用Linq方法的返回时间

C# 使用Linq方法的返回时间,c#,linq-to-entities,C#,Linq To Entities,一个朋友向我展示了Linq的声明: records.Where( r => r.Name == "Henry Clay" ).FirstOrDefault(); 抛开FirstOrDefault()可以获取lambda的事实不谈,所有的Henry Clay记录在都转到FirstOrDefault()之前都要检查“Henry Clay”,还是Where方法只返回第一个 换句话说,一些Henry Clay记录可能永远不会传递给FirstOrDefault吗?假设您在最后找到一个项,您将不会迭

一个朋友向我展示了Linq的声明:

records.Where( r => r.Name == "Henry Clay" ).FirstOrDefault();
抛开FirstOrDefault()可以获取lambda的事实不谈,所有的Henry Clay记录在都转到FirstOrDefault()之前都要检查“Henry Clay”,还是Where方法只返回第一个


换句话说,一些Henry Clay记录可能永远不会传递给FirstOrDefault吗?

假设您在最后找到一个项,您将不会迭代整个源序列。第一件物品一归还,您将立即停止

这里有一个有用的类比。想象一下,一群人坐在一张桌子旁边。“迈克”坐在最左边。每当他旁边的人向他要东西时,他都会从一堆纸中拿出一张给下一个人。他将成为底层数据
记录的“枚举器”

坐在他旁边的将是“弗雷德”。弗雷德,当被要求买东西时,会向迈克要东西。如果迈克给他的物品上面写着“亨利·克莱”,那么他会把它交给下一个人,如果没有,他会向迈克索要另一件物品。这将一直持续下去,直到弗雷德最终得到一件符合他条件的物品,或者迈克的物品用完。他代表的是
Where
enumerator

弗雷德右边是“亚伦”。Aaron在被要求提供物品时,会向Fred提供物品。当他从弗雷德那里得到一件物品时,他会把它传递给下一个人,然后下次有人要一件物品时,他会立即说“不,我已经做完了”,而不向弗雷德要求任何其他东西。他代表的是
FirstOrDefault


每个人,当被要求从旁边的人那里得到一个项目时,只有当被要求时,才会从他们的“来源”那里得到一个项目,处理它,或者做他们需要做的任何事情,为下一个人生成一个项目。你可以想象,使用这个例子,一旦Aaron得到他的第一件物品,很可能会有几张纸留在纸堆上。它们将留在那里,任何人都不会处理,因为Aaron永远不会向Fred索要第二个项目。

假设您在最后找到一个项目,您将不会重复整个源序列。第一件物品一归还,您将立即停止

这里有一个有用的类比。想象一下,一群人坐在一张桌子旁边。“迈克”坐在最左边。每当他旁边的人向他要东西时,他都会从一堆纸中拿出一张给下一个人。他将成为底层数据
记录的“枚举器”

坐在他旁边的将是“弗雷德”。弗雷德,当被要求买东西时,会向迈克要东西。如果迈克给他的物品上面写着“亨利·克莱”,那么他会把它交给下一个人,如果没有,他会向迈克索要另一件物品。这将一直持续下去,直到弗雷德最终得到一件符合他条件的物品,或者迈克的物品用完。他代表的是
Where
enumerator

弗雷德右边是“亚伦”。Aaron在被要求提供物品时,会向Fred提供物品。当他从弗雷德那里得到一件物品时,他会把它传递给下一个人,然后下次有人要一件物品时,他会立即说“不,我已经做完了”,而不向弗雷德要求任何其他东西。他代表的是
FirstOrDefault


每个人,当被要求从旁边的人那里得到一个项目时,只有当被要求时,才会从他们的“来源”那里得到一个项目,处理它,或者做他们需要做的任何事情,为下一个人生成一个项目。你可以想象,使用这个例子,一旦Aaron得到他的第一件物品,很可能会有几张纸留在纸堆上。它们将留在那里,任何人都不会处理,因为Aaron永远不会向Fred索要第二件物品。

不,所有元素都是惰性执行的。当您按照如下方式重写查询时,可以看到这一点:

records.Where(r =>
{
    Console.WriteLine(r.Name);
    return r.Name == "Henry Clay";
})
.FirstOrDefault();
强制执行时,结果将非常不同,例如使用
ToArray()

records.Where(r =>
{
    Console.WriteLine(r.Name);
    return r.Name == "Henry Clay";
})
.ToArray()
.FirstOrDefault();

在最后一种情况下,
ToArray()
将强制迭代
记录
集合中的所有元素,否则,
FirstOrDefault()
将确保在where谓词第一次返回true后,集合停止迭代。

否,所有元素都是延迟执行的。当您按照如下方式重写查询时,可以看到这一点:

records.Where(r =>
{
    Console.WriteLine(r.Name);
    return r.Name == "Henry Clay";
})
.FirstOrDefault();
强制执行时,结果将非常不同,例如使用
ToArray()

records.Where(r =>
{
    Console.WriteLine(r.Name);
    return r.Name == "Henry Clay";
})
.ToArray()
.FirstOrDefault();

在最后一种情况下,
ToArray()
将强制迭代
记录
集合中的所有元素,否则,
FirstOrDefault()
将确保在where谓词第一次返回true后,集合停止迭代。

。ToArray()强制完成前面方法的原因是什么?@micahhoover
ToArray
不使用延迟执行。调用时,它将立即处理整个输入序列并生成结果。LINQ中所有的
To
方法的作用方式都是相同的,所有的聚合运算符(
Count
Sum
Average
aggregate
,等等)也是一样的。实际上这很简单。ToArray()创建一个包含所有元素的数组,这意味着它必须循环整个集合来构建数组。另一方面,
IEnumerable
(what
Where
返回的内容)是一个仅向前的流游标。ToArray()强制完成前面方法的原因是什么?@micahhoover
ToArray
不使用延迟执行。调用时,它将立即处理整个输入序列并生成结果。LINQ中所有的
To
方法的作用方式都是相同的,所有的聚合运算符(
Count
Sum
Average
aggregate
,等等)也是一样的。实际上这很简单。ToArray()创建一个包含所有元素的数组,这意味着