LINQ延迟执行差异解析:为何两个函数输出结果不同?
为什么两个LINQ延迟执行的函数表现不一致?
这本质是数据源的可变性差异导致的,LINQ的Where方法是延迟执行(即查询逻辑直到遍历的时候才会真正运行),但不同类型的数据源在后续修改时的行为完全不同:
分析func1的执行逻辑
先看func1的代码:
static void func1() { IEnumerable<char> s = "I am Tommy Shelby"; var query = s.Where(x => x != 'a'); s = ""; foreach (var item in query) { Console.Write(item); } }
字符串是不可变类型:当你初始化s为"I am Tommy Shelby"时,这个字符串对象在内存中是固定不变的。后续s = ""只是把变量s的指向改成了一个新的空字符串对象,但Where查询捕获的是最初那个完整字符串的引用,而非变量s本身。
当foreach遍历query时,才会执行过滤逻辑,此时操作的还是最初的完整字符串,因此能输出过滤掉'a'后的结果。
分析func2的执行逻辑
再看func2的代码:
static void func2() { List<int> num = new List<int> { 1, 2, 3, 4 }; var query2 = num.Where(x => x % 2 == 0); num.Clear(); foreach (var item in query2) { Console.Write(item); } }
List<T>是可变集合:变量num始终指向同一个List对象。Where查询捕获的是这个List对象的引用,当你调用num.Clear()时,是直接修改了该List对象内部的内容(清空所有元素)。
当foreach遍历query2时,才会执行过滤逻辑,此时原List已经是空的,自然没有元素可以输出,所以结果为空。
总结
LINQ延迟执行时会保留对数据源对象的引用,但:
- 对于不可变类型(如字符串):修改变量的指向不会影响原对象,查询最终基于初始的数据源对象执行
- 对于可变集合(如
List<T>):修改集合的内部状态会直接影响后续查询的执行结果
内容的提问来源于stack exchange,提问作者rohan
相关产品推荐
相关产品推荐

