我有一个List<String> myList
.
我想获取此列表中符合某些条件的前 10 个项目(例如,假设.Contains("a")
)。
我有:
Var results = myList.Where(o=>o.Contains("a")).Take(10);
哪个工作正常,但 LINQ 是否执行了Where
检索所有符合此条件的项目,然后只取了前 10 个?或者这是否会以考虑整个 LINQ 语句的方式进行编译(即它将执行Where
但只执行到 10 个项目)?
我有一个List<String> myList
.
我想获取此列表中符合某些条件的前 10 个项目(例如,假设.Contains("a")
)。
我有:
Var results = myList.Where(o=>o.Contains("a")).Take(10);
哪个工作正常,但 LINQ 是否执行了Where
检索所有符合此条件的项目,然后只取了前 10 个?或者这是否会以考虑整个 LINQ 语句的方式进行编译(即它将执行Where
但只执行到 10 个项目)?
LINQ 使用惰性求值。当您执行以下行时:
var results = myList.Where(o=>o.Contains("a")).Take(10);
没发生什么事。仅构建查询。当您枚举results
, (例如使用 aforeach
或 a ToList()
)时,Where
andTake
将应用于myList
:Where
将根据需要执行,直到true
找到最多 10 个值。
Where 语句返回一个等待枚举的 IEnumerable。Where 逻辑的执行会延迟,直到您“询问”IEnumerable 的下一个值。
Take(10) 语句就是这样做的 - 要求它为 Where 条件提供“下一个匹配项”。这将执行 10 次,然后完成。但是当然,出于同样的原因,直到您枚举最终返回值(在您的情况下为结果),才会真正执行 Take(10) 语句的逻辑。
所以是的,它有点优化,但可能不像你想象的那样。
看下面的代码:
using System;
using System.Collections.Generic;
using System.Linq;
public class Test {
public static void Main(String[] args) {
var l = new List<String>() { "a", "ab", "b", "bb", "bc", "ba", "c", "ca", "cc" };
foreach (var s in l.Where(e => { Console.WriteLine(e); return e.Contains("a"); }).Take(3)) {
Console.WriteLine("loop: {0}", s);
}
}
}
输出是:
a
loop: a
ab
loop: ab
b
bb
bc
ba
loop: ba
所以你可以看到它是优化的(“c”之后的字符串没有被评估)。