2012-02-03 49 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 

Tôi đã dự kiến ​​dòng trên sẽ trả về giá trị đúng. Tại sao tôi không thể thiết lập các thuộc tính của các biến lặp trong vòng lặp foreach?Tại sao tôi không thể đặt thuộc tính của biến lặp trong vòng lặp foreach?

+3

bản sao của: http://stackoverflow.com/questions/776430/why-is-the-iteration-variable-in-ac-sharp-foreach-statement-read-only –

+4

Đó không phải là một giá trị trùng lặp, đây không phải là về việc gán cho biến vòng lặp. Đây là một vấn đề thực hiện hoãn lại. –

+0

@ M.Babcock Tôi không nghĩ đó là câu hỏi trùng lặp. câu hỏi trong liên kết cố gắng gán cho biến lặp chính nó, trong khi câu hỏi của tôi gán cho thuộc tính varaible của iteration. nhưng cảm ơn! – Yeonho

Trả lời

19

people là định nghĩa truy vấn có thực thi hoãn lại. Tìm kiếm của bạn trên truy vấn không liên quan, điều này không phải là về việc không thể thiết lập thuộc tính. Khi bạn gọi First(), bạn chạy lại truy vấn.

Để rõ ràng, định nghĩa truy vấn ở đây là cho các phần tử bằng số, tạo một Person mới và gán giá trị của phần tử số hiện tại vào thuộc tính Name của Person. Khi bạn lặp lại trong vòng lặp foreach, truy vấn sẽ đánh giá và bạn tạo các đối tượng Person mới. Nhưng những đối tượng Person đó không có trong truy vấn, nó chỉ là một định nghĩa! Chạy truy vấn lại thực hiện lại định nghĩa, tạo ra các đối tượng Person khác nhau. Thực tế là bạn đã sửa đổi kết quả ban đầu của truy vấn không ảnh hưởng đến tập kết quả thứ hai.

Nếu bạn muốn một thực hiện ngay lập tức, sử dụng

var people = numbers.Select(n => new Person() 
    { 
     Name = n.ToString() 
    }).ToList(); 

Bạn sẽ tìm thấy những thay đổi của bạn trong gắn bó vòng lặp, bởi vì bây giờ people là danh sách cụ thể thay vì một định nghĩa truy vấn.

foreach (var person in people) 
{ 
    person.Name = newName; 
} 

Debug.WriteLine(people.First().Name.Equals(newName)); // returns true 
+0

oh ! Tôi hiểu rồi. cảm ơn! – Yeonho

6

Đây là ví dụ hoàn hảo về deferred execution.

Nếu bạn thử ví dụ này, nó hoạt động như bạn mong đợi từ khi thực hiện truy vấn 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; 
Các vấn đề liên quan