为啥我不能在 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 循环中设置迭代变量的属性?的主要内容,如果未能解决你的问题,请参考以下文章

Java中foreach为啥不能给数组赋值

无法分配给项目,因为它是一个 foreach 迭代变量 [重复]

在 C# 中,为啥我不能在 foreach 循环中修改值类型实例的成员?

为啥我不能访问这个数组 ForEach 循环中的数据? SwiftUI

为啥我不能使用 foreach 循环更新数组中的数据?

为啥在foreach循环中不能修改值类型实例