2012-02-03 54 views
12
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循环中设置迭代变量的属性?为什么我不能在foreach循环中设置迭代变量的属性?

+3

重复的:http://stackoverflow.com/questions/776430/why-is-the-iteration-variable-in-ac-sharp-foreach-statement-read-only – 2012-02-03 02:39:56

+4

这不是一个有效的重复,这不是关于分配给循环变量。这是延迟执行的问题。 – 2012-02-03 02:44:34

+0

@ M.Babcock我不认为这是一个重复的问题。链接中的问题试图分配给迭代变量本身,而我的问题分配给迭代变量的属性。但是谢谢! – Yeonho 2012-02-03 02:45:28

回答

19

people是延迟执行的查询定义。您对查询的foreach是无关紧要的,这不是无法设置属性。当你调用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 
+0

中所述哦!我知道了。谢谢! – Yeonho 2012-02-03 02:46:19

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; 
相关问题