string newName = "new name";
int[] numbers = new int[] { 1, 2, 3 };
var people = numbers.Select(n => new Person()
{
Name = n.ToString()
});
foreach (var person in people)
{
person.Name = newName;
}
Debug.WriteLine(people.First().Name == newName); // returns false
我预计上面的行会返回true。为什么我不能在foreach循环中设置迭代变量的属性?
答案 0 :(得分:19)
people
是具有延迟执行的查询定义。您对查询的预测是无关紧要的,这与无法设置属性无关。当您调用First()
时,会再次运行查询。
要清楚,这里的查询定义是对于数字中的元素,创建一个新Person并将当前数字元素的值赋给Person的Name属性。当您在foreach循环中进行迭代时,查询将进行求值,并创建新的Person对象。但那些Person对象不在查询中,它只是一个定义!再次运行查询会再次执行定义,创建不同的 Person对象。您修改查询的原始结果这一事实不会影响第二组结果。
如果您想立即执行,请使用
var people = numbers.Select(n => new Person()
{
Name = n.ToString()
}).ToList();
你会在循环中发现你的变化,因为现在people
是一个具体的列表而不是查询定义。
foreach (var person in people)
{
person.Name = newName;
}
Debug.WriteLine(people.First().Name.Equals(newName)); // returns true
答案 1 :(得分:6)
这是deferred execution的完美示例。
如果您尝试此示例,它会按预期工作,因为ToList
执行查询。
string newName = "new name";
int[] numbers = new int[] { 1, 2, 3 };
var people = numbers.Select(n => new Person()
{
Name = n.ToString()
}).ToList(); // <===== here
foreach (var person in people)
{
person.Name = newName;
}
var b = people.First().Name == newName;