2011-05-21 27 views
5

Esto me deja perplejo. Estoy usando PetaPoco para recuperar algunos valores de una base de datos, y luego recorrerlos y recuperar un valor para asignar a una de las propiedades de cada objeto.¿Modificar una propiedad de un objeto dentro de un bucle foreach no funciona?

public IEnumerable<RetreaveIndex> FillResults(IEnumerable<RetreaveIndex> results) 
    { 
     //add the associated users 
     foreach (RetreaveIndex index in results) 
     { 
      index.AssociatedUsers = _registeredUserDao.GetUsersByIndex(index).ToList(); 
     } 
     return results; 
    } 

Cuando me puse un punto de interrupción durante el bucle foreach, la propiedad AssociatedUsers se está estableciendo correctamente. during foreach loop

pero luego en un punto de interrupción al final del ciclo, ¿no lo guardó? enter image description here

Estoy confundido, ¿Index no debería ser una referencia a un lugar en la memoria que se está modificando? Es un objeto después de todo. ¿Que me estoy perdiendo aqui?

Respuesta

8
  1. ¿Qué es la implementación de IEnumerable? ¿Podría devolver una copia del objeto?

  2. ¿RetreaveIndex es una estructura, y por lo tanto un tipo de valor? Si es así, entonces la variable index será una copia.

+0

su un objeto (véase la parte inferior de la pregunta original).Eché un vistazo al código fuente de PetaPoco, y parece que el método al que llamaba, Query (), utiliza Yield Return para devolver un IENumerable. Cuando cambié mi llamada a Fetch () que devuelve una lista funcionó. Tal vez necesito leer más acerca de rendimiento, pensé que era solo azúcar sintáctico para construir una lista de algún tipo, ¿supongo que estoy equivocado? – RodH257

+1

return return hace que el cuerpo del método se divida en una sentencia de caso gigante que se convierte en el cuerpo del método MoveNext de una nueva clase IEnumerator. –

+0

He estado trabajando con IEnumerables durante años y, sorprendentemente, esta es la primera vez que toco esto ... (lo que me desconcertó por completo) ¡Salud! – FBryant87

3

Dependiendo de cómo el IEnumerable pasado es implementado, no tiene ningún requisito de que la próxima vez que enumera sobre los datos que se devuelven los mismos objetos que antes. Intenta convertir el IEnumerable en una lista antes del ciclo foreach y devuelve ese insead.

1

Desde el project web site:

de consulta vs Fetch

La clase de base de datos tiene dos métodos para recuperación de registros de consulta y de Fetch. Estos son más o menos idénticos excepto retornos obtener una lista de <> POCO de mientras que el rendimiento de consultas utiliza retorno a iterar sobre los resultados sin cargar todo el conjunto en la memoria.

En otras palabras, Query vuelve a cargar los valores del almacén de respaldo cada vez, y no guarda un artículo en torno después de que se han enumerado. Cuando vaya a mirar un artículo nuevamente después del final de su ciclo, ese artículo se volverá a cargar desde la tienda de respaldo.

0

En realidad, lo que está pasando es que está malinterpretando el resultado de la sintaxis yield return.

Lo que sucede es que a medida que itera sobre el IEnumerable devuelto desde yield return, se está ejecutando el código que sigue a yield return. En términos técnicos, yield return está haciendo una evaluación perezosa. Por lo tanto, en el efecto neto de su foreach, el bucle es que está llamando al código para hacer que el artículo esté en el IEnumerable para cuantos artículos hay en ese IEnumerable.

El siguiente post de CodeProject hace un excelente trabajo de explicar este comportamiento: http://www.codeproject.com/Articles/38097/The-Mystery-Behind-Yield-Return.aspx

Cuestiones relacionadas