LINQ生成的IEnumerable与原List的关联及延迟执行问题解析
问题解析
你的代码如下:
var list = new List<Test>() { new Test("Test1"), new Test("Test2") }; var enumerable = list.Where(t => t.Content == "Test1"); Console.WriteLine($"Enumerable count: {enumerable.Count()}"); Console.WriteLine($"List count: {list.Count}"); list.RemoveAll(t => t.Content == "Test1"); Console.WriteLine($"Enumerable count: {enumerable.Count()}"); Console.WriteLine($"List count: {list.Count}");
你预期的输出:
Enumerable count: 1 List count: 2 Enumerable count: 1 List count: 1
实际输出:
Enumerable count: 1 List count: 2 Enumerable count: 0 List count: 1
核心原因:LINQ的延迟执行
这是LINQ查询的延迟执行特性导致的:
- 调用
list.Where(...)时,并没有立刻执行过滤操作生成新集合,而是返回了一个只记录查询逻辑(“筛选Content为Test1的元素”)和原List引用的查询对象(IEnumerable<T>类型)。 - 每次调用
enumerable.Count()(或者遍历这个IEnumerable),都会重新执行一遍查询逻辑——也就是再次去原List里查找符合条件的元素。 - 当你用
list.RemoveAll(...)删掉Test1元素后,原List里已经没有符合条件的元素了,所以第二次Count()返回0。
加.ToList()符合预期的原因
在Where后追加.ToList(),会立即执行查询,把过滤结果存入一个全新的List<T>集合。这个新集合和原List完全独立,后续原List的修改不会影响它,所以第二次Count()依然返回1。
总结一下:
- 直接用
Where返回的IEnumerable:是动态的查询规则,每次使用都会重新查询原List - 加
.ToList():是查询结果的静态快照,和原List无关联
内容的提问来源于stack exchange,提问作者kling
相关产品推荐
相关产品推荐

