C# 为什么在使用foreach时不执行此LINQ查询?
在LINQ语句中创建新对象时,例如:C# 为什么在使用foreach时不执行此LINQ查询?,c#,.net,linq,foreach,deferred-execution,C#,.net,Linq,Foreach,Deferred Execution,在LINQ语句中创建新对象时,例如: var list = new List<string>() { "a", "b", "c" }; var created = from i in list select new A(); 然后使用foreach循环修改中的属性: foreach (var c in created) { c.Label = "Set"; } 为什么在以后访问IEnumerable中的对象时不设置这些值。例如,以下断言失败: Assert.AreEqua
var list = new List<string>() { "a", "b", "c" };
var created = from i in list select new A();
然后使用foreach循环修改中的属性:
foreach (var c in created) {
c.Label = "Set";
}
为什么在以后访问IEnumerable
中的对象时不设置这些值。例如,以下断言失败:
Assert.AreEqual("Set", created.ElementAt(2).Label);
我想知道为什么会这样。我希望foreach语句执行查询,并触发对象的创建。MSDN文档状态:
我用.NET4.5和Mono3.2.0复制了这种行为。在访问创建的对象之前调用
IEnumerable
上的ToList
,可以解决此问题。之所以发生此问题,是因为创建的是一个查询,而不是结果。因此,每次枚举它时,您都要从头开始重新计算Select
如果您希望这样做,请将created
设置为实际列表,而不仅仅是表示查询的IEnumerable
例如,添加:
created = created.ToList();
你说:
我希望foreach语句执行查询,并触发对象的创建
这正是正在发生的事情。问题在于,对象的创建是在每次迭代创建的时发生的,而不仅仅是第一次。由于ElementAt()
方法在created
上迭代,它只是再次创建新的A
。它与“not executed”(未执行)相反,执行两次,第二次执行时,会创建一组新的A
。因为created
是一个查询,而不是一个集合。每次访问它时,都会再次执行它。因此,如果在foreach
之后再次枚举查询,您将得到一组新的IEnumerable
。这就是延期执行的本质。如果您要查询一个现有的A
集合,您需要更改现有的持久对象。
created = created.ToList();