1

一个朋友给我看了这个 Linq 语句:

records.Where( r => r.Name == "Henry Clay" ).FirstOrDefault();

撇开 FirstOrDefault() 可以采用 lambda 的事实不谈,是否所有 Henry Clay 记录都在全部转到 FirstOrDefault() 之前检查“Henry Clay”,还是 Where 方法只返回第一个?

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

4

2 回答 2

5

假设您在最后找到一个项目,您将不会迭代整个源序列。您将在返回第一个项目后立即停止。

这是一个有用的类比。想象一群人坐在一张桌子旁。“迈克”坐在最左边。每当他旁边的人向他要一件东西时,他都会从一摞纸中拿出一张纸递给下一个人。他将成为基础数据的“枚举者” records

坐在他旁边的是“弗雷德”。弗雷德在被问到一件物品时,会向迈克要一件物品。如果迈克给他的物品上写着“亨利克莱”,那么他会把它给下一个人,如果没有,他会向迈克要另一个物品。这将一直持续到 Fred 最终得到符合他条件的物品,或者 Mike 用完物品。他代表Where普查员。

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

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

于 2012-10-29T20:29:24.787 回答
5

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

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()将强制迭代records集合中的所有元素,否则,FirstOrDefault()将确保集合在 where 谓词第一次返回 true 后停止迭代。

于 2012-10-29T20:30:08.967 回答