为啥我不能在 foreach 循环中设置迭代变量的属性?
Posted
技术标签:
【中文标题】为啥我不能在 foreach 循环中设置迭代变量的属性?【英文标题】:Why can't I set properties of iteration variables in a foreach loop?为什么我不能在 foreach 循环中设置迭代变量的属性? 【发布时间】:2012-02-25 17:40:01 【问题描述】: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 循环中设置迭代变量的属性?
【问题讨论】:
重复:***.com/questions/776430/… 这不是一个有效的副本,这与分配给循环变量无关。这是延迟执行的问题。 @M.Babcock 我不认为这是一个重复的问题。链接中的问题试图分配给迭代变量本身,而我的问题分配给迭代变量的属性。不过谢谢! @M.Babcock,这不是那个问题的重复。这个问题是关于修改迭代器本身的,因为迭代器是不可变的,所以无法做到这一点。然而,没有什么能阻止修改迭代器的内容(参见***.com/a/776780/495041)。这种行为的原因是变量 people 是 IQuerable ,它在 foreach 循环运行时执行一次,在调用 First() 时再次执行,如 ***.com/a/9123015/495041 中所述 【参考方案1】:people
是一个延迟执行的查询定义。您对查询的 foreach 无关紧要,这与无法设置属性无关。当您调用 First()
时,您再次运行查询。
明确一点,这里的查询定义是对于numbers中的元素,新建一个Person,并将当前number元素的值赋给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
【讨论】:
【参考方案2】:这是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;
【讨论】:
以上是关于为啥我不能在 foreach 循环中设置迭代变量的属性?的主要内容,如果未能解决你的问题,请参考以下文章
无法分配给项目,因为它是一个 foreach 迭代变量 [重复]
在 C# 中,为啥我不能在 foreach 循环中修改值类型实例的成员?