简体   繁体   English

为什么在使用foreach时不执行此LINQ查询?

[英]Why is this LINQ query not executed when using foreach?

When creating new objects in a LINQ statement, for example: 在LINQ语句中创建新对象时,例如:

var list = new List<string>() { "a", "b", "c" };
var created = from i in list select new A();

With class A looking like this: A类看起来像这样:

class A
{
    public string Label;
}

And then modifying properties in A with a foreach loop: 然后使用foreach循环修改A中的属性:

foreach (var c in created) {
    c.Label = "Set";
}

Why are the values not set when accessing the objects in the IEnumerable afterwards. 此后为什么在IEnumerable访问对象时未设置值。 Eg the following assertion fails: 例如,以下断言失败:

Assert.AreEqual("Set", created.ElementAt(2).Label);

I wonder why this happens. 我不知道为什么会这样。 I would expect the foreach-statement to execute the query, and trigger the creation of the objects. 我希望foreach语句能够执行查询,并触发对象的创建。 MSDN documentation states: "Execution of the query is deferred until the query variable is iterated over in a foreach or For Each loop" . MSDN文档指出: “查询的执行被推迟,直到在foreach或For Each循环中迭代查询变量为止”

I have reproduced this behavior with .NET 4.5 and Mono 3.2.0. 我已经用.NET 4.5和Mono 3.2.0复制了此行为。 Calling ToList on the IEnumerable before accessing the created object makes this problem go away. 在访问创建的对象之前在IEnumerable上调用ToList可以使此问题消失。

It's happening because created is a query, not a result. 发生这种情况是因为created是查询,而不是结果。 So, every time you enumerate it, you're evaluating the Select over again from scratch. 因此,每次枚举时,您都在重新评估Select

If you want this to work, make created an actual list, rather than just an IEnumerable representing a query. 如果您希望此方法有效,请created一个实际列表,而不只是一个表示查询的IEnumerable

For example, add: 例如,添加:

created = created.ToList();

You say: 你说:

I would expect the foreach-statement to execute the query, and trigger the creation of the objects 我希望foreach语句能够执行查询,并触发对象的创建

This is exactly what is happening. 这正是正在发生的事情。 The problem is the creation of the objects happens every time you iterate over created , not just the first time. 问题在于,每次迭代created对象时都会发生对象的created ,而不仅仅是第一次。 Since the ElementAt() method iterates over created , it's just creating new A s again. 由于ElementAt()方法遍历created ,因此仅在再次创建新A

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM