以下LINQ语句如何工作?


160

以下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呢?


102
查询表达式的结果是查询,而不是查询的执行。
埃里克·利珀特

6
有关较少的信息,请参阅此问题的公认答案。
丹尼尔(Daniel)

9
当然,您可以想到实际上可以概括问题的标题。
马特·鲍尔

2
我对否决票(目前是6个,不是我的)的猜测是,他们认为问题标题太笼统了,不是一个好问题。但是,看到赞成票的数量增加,并成为新闻通讯中本周的首要问题,我认为您不必为此担心太多。
亚伯

Answers:


235

输出是2,4,6,8由于推迟执行

查询实际上是在迭代查询变量时执行的,而不是在创建查询变量时执行的。这称为延迟执行。

-Suprotim Agarwal,“ LINQ中的延迟查询与即时查询执行”

还有另一种称为即时查询执行的执行,对缓存查询结果很有用。再次从Suprotim Agarwal:

要强制立即执行不产生单例值的查询,可以 在查询或查询变量上调用ToList(), ToDictionary(), ToArray(), Count(), Average()or 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);
 }

8
Count(),Max(),Avg(),Sum()以及可能需要考虑整个列表的其他方法,也会导致查询评估。
肯尼斯(Kenned),2013年

1
我经常想到将“ filteredList”作为变量,而不是将“ filterList()”作为方法,这种想法是,您每次要过滤列表时都要对其进行迭代,而不是调用方法。可能是一种有趣的,甚至不寻常的,甚至可能是不完美的性能处理方法。
Katana314 2013年

4
@Sebastian -继@ Kenned的评论,.First().FirstOrDefault().Single()并且.SingleOrDefault()还引发了查询的评价。
Scotty.NET 2013年

4
令人惊讶的是,您在不到30秒的时间内得到了答案:D
MC

2
@MC我不知道你为什么问这个问题。一次没有给出完整的答案。它被编辑了几次。
Atish Dipongkor-MVP

11

这是由于延迟执行而发生的,这意味着直到某个地方需要表达式的计算才执行。如果数据太大,这会使性能更好。


3
您可能会感到有些微不足道,因为这也可能意味着您的昂贵枚举正在多次执行。在这种情况下,您甚至可能会遭受性能损失。
绝望的鬼脸


0

当您使用从LINQ获得的IEnumerable <>时,仅创建一个Enumerator类,并且仅当您步行使用它时才开始迭代。


-1

由于延迟执行而获得此结果,这意味着直到第一次访问结果才实际评估结果。

为了更加清楚,只需在片段的末尾添加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);
    }

您实际上尝试过吗?我进入10输出。
Mark Hurd

好捕获@MarkHurd是,没有添加.ToList()。现在编辑了帖子,它应该给出预期的输出。我的期望是只有在第一次使用var时才对表达式进行评估,但看起来每次都在对其进行评估
sandeep

现在,它将不会包含8在任何输出中。
Mark Hurd
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.