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

时间:2013-09-20 12:45:11

标签: c# .net linq foreach deferred-execution

在LINQ语句中创建新对象时,例如:

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

A级看起来像这样:

class A
{
    public string Label;
}

然后使用foreach循环修改A中的属性:

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

为什么之后访问IEnumerable中的对象时未设置值。例如。以下断言失败:

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

我想知道为什么会这样。我希望foreach语句执行查询,并触发对象的创建。 MSDN文档说明:"Execution of the query is deferred until the query variable is iterated over in a foreach or For Each loop"

我已经使用.NET 4.5和Mono 3.2.0重现了这种行为。 ToList会使这个问题消失。

1 个答案:

答案 0 :(得分:6)

这种情况正在发生,因为created是一个查询,而不是一个结果。因此,每次枚举它时,您都是从头开始重新评估Select

如果您希望这样做,请将created设为实际列表,而不仅仅是代表查询的IEnumerable

例如,添加:

created = created.ToList();

你说:

  

我希望foreach语句执行查询,并触发对象的创建

这正是发生的事情。问题是每次迭代created时都会发生对象的创建,而不仅仅是第一次。由于ElementAt()方法迭代created,因此只是再次创建新的A