2012-02-03 55 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; 
相關問題