LINQ中.Where方法底层实现及链式调用枚举次数疑问
关于LINQ链式Where调用的枚举次数解惑
你的理解有误,实际仅会对原始集合执行一次枚举,核心原因在于LINQ的「延迟执行」特性,结合Where方法的迭代器实现来具体解释:
1. 延迟执行的本质
Where是LINQ中的延迟执行操作,它返回的IEnumerable<TSource>并不会立即遍历原始集合。只有当后续调用立即执行操作(比如ToList()、Count())时,才会触发真正的枚举流程。
2. 链式调用的执行流程
以collection.Where(pred1).Where(pred2).ToList()为例,执行过程是流水线式的:
- 当
ToList()开始构建列表时,它会遍历第二个Where返回的序列; - 第二个
Where遍历第一个Where返回的序列; - 第一个
Where遍历原始集合。
整个过程是单轮遍历、逐个处理:原始集合的每个元素被取出后,先经过pred1判断,符合条件的再传入pred2判断,最终符合条件的元素才会被添加到List中。不存在“第一个Where先遍历完整个集合生成中间结果,再由第二个Where遍历中间结果”的情况。
3. 结合Where的实现代码理解
你给出的Where实现中使用了yield return,这使得方法成为一个迭代器:
public static IEnumerable<TSource> Where<TSource>(this IEnumerable<TSource> source, Func<TSource,bool> predicate) { foreach (TSource element in source) if (predicate (element)) yield return element; }
- 调用
Where时,方法并不会立即执行foreach循环,只有当这个迭代器被遍历(比如被后续的Where或ToList()遍历)时,foreach才会逐步执行; - 第一个
Where的foreach,会在第二个Where遍历它的时候才逐步取原始集合的元素;第二个Where的foreach,则在ToList()遍历它的时候逐步执行。
这种嵌套的迭代执行,最终只会让原始集合被枚举一次,所有过滤逻辑都在这一轮枚举中完成。
内容的提问来源于stack exchange,提问作者jon bee
相关产品推荐
相关产品推荐

