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

Esperaba que la línea anterior fuera verdadera. ¿Por qué no puedo establecer las propiedades de las variables de iteración dentro de un ciclo foreach?¿Por qué no puedo establecer las propiedades de las variables de iteración en un ciclo foreach?

+3

duplicado de: http://stackoverflow.com/questions/776430/why-is-the-iteration-variable-in-ac-sharp-foreach-statement-read-only –

+4

Eso no es válida duplicado, esto no se trata de asignar a la variable de bucle. Este es un problema de ejecución diferida. –

+0

@ M.Babcock No creo que sea una pregunta duplicada. la pregunta en el enlace intenta asignar a la variable de iteración en sí, mientras que mi pregunta se asigna a la propiedad de la iteración varaible. ¡pero gracias! – Yeonho

Respuesta

19

people es una definición de consulta con ejecución diferida. Su enfoque sobre la consulta es irrelevante, no se trata de una incapacidad para establecer una propiedad. Cuando invoca First(), , ejecuta la consulta de nuevo.

Para ser claros, la definición de consulta aquí es que para los elementos en números, cree una nueva Persona y asigne el valor del elemento numérico actual a la propiedad Nombre de la persona. Cuando itera en el bucle foreach, la consulta evalúa y crea nuevos objetos Persona. Pero esos objetos Person no están en la consulta, ¡es solo una definición! La ejecución de la consulta nuevamente ejecuta la definición nuevamente, creando diferentes objetos de persona. El hecho de que haya modificado los resultados originales de la consulta no afecta el segundo conjunto de resultados.

Si desea una ejecución inmediata, utilice

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

Encontrará los cambios en la adherencia de bucle, porque ahora people es una lista de hormigón en vez de una definición de la consulta.

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

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

oh ! Lo entiendo. ¡Gracias! – Yeonho

6

Este es un ejemplo perfecto de deferred execution.

Si prueba este ejemplo, funciona como esperaba ya que el ToList ejecuta la consulta.

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; 
Cuestiones relacionadas