以下LINQ语句如何运作?
这是我的代码:
var list = new List<int>{1,2,4,5,6};
var even = list.Where(m => m%2 == 0);
list.Add(8);
foreach (var i in even)
{
Console.WriteLine(i);
}
输出: 2, 4, 6, 8
为什么不2, 4, 6
?
答案 0 :(得分:235)
由于deferred execution,输出为2,4,6,8
。
查询实际上是在查询变量时执行的 迭代,而不是在创建查询变量时。 这称为延迟执行。
- Suprotim Agarwal,"Deferred vs Immediate Query Execution in LINQ"
还有另一个名为Immediate Query Execution的执行,它对缓存查询结果很有用。来自Suprotim Agarwal再次:
要强制立即执行不产生单例值的查询,可以在查询或查询变量上调用
ToList(), ToDictionary(), ToArray(), Count(), Average()
或Max()
方法。这些被称为转换运算符,允许您创建结果的副本/快照,并且可以多次访问,而无需重新执行查询。
如果您希望输出为2,4,6
,请使用.ToList()
:
var list = new List<int>{1,2,4,5,6};
var even = list.Where(m => m%2 == 0).ToList();
list.Add(8);
foreach (var i in even)
{
Console.WriteLine(i);
}
答案 1 :(得分:11)
这是因为延迟执行而发生的,这意味着表达式的计算在某个地方需要之前不会执行。如果数据太大,这会使性能更好。
答案 2 :(得分:0)
这样做的原因是延迟执行lambda表达式。当您开始在foreach循环中进行迭代时,将执行查询。
答案 3 :(得分:0)
当您使用IEnumerable&lt;&gt;时从LINQ获得,只创建一个Enumerator类,迭代只在你在一些walk中使用时启动。
答案 4 :(得分:-1)
由于延迟执行,您得到此结果,这意味着在第一次访问结果之前,实际上不会对结果进行评估。
为了使其更清晰,只需在你的snipet末尾添加10,然后再打印,你就不会得到10个输出
var list = new List<int>{1,2,4,5,6};
var even = list.Where(m => m%2 == 0).Tolist();
list.Add(8);
foreach (var i in even)
{
Console.WriteLine(i);
}
//new*
list.Add(10);
foreach (var i in even)
{
Console.WriteLine(i);
}