Esto realmente me dejó perplejo, ya que esperaba un comportamiento de 'pasar por referencia'. Esperaba que este código imprimiera "5,5,5", pero en su lugar imprime "7,7,7".
IEnumerable<MyObj> list = Enumerable.Range(0, 3).Select(x => new MyObj { Name = 7 }); Alter(list); Console.WriteLine(string.Join(',',list.Select(x => x.Name.ToString()))); Console.ReadLine(); void Alter(IEnumerable<MyObj> list) { foreach(MyObj obj in list) { obj.Name = 5; } } class MyObj { public int Name { get; set; } }Mientras que esto imprime "7,7,7" como se esperaba.
IEnumerable<MyObj> list = Enumerable.Range(0, 3).Select(x => new MyObj { Name = 7 }).ToList(); Alter(list); Console.WriteLine(string.Join(',',list.Select(x => x.Name.ToString()))); Console.ReadLine(); void Alter(IEnumerable<MyObj> list) { foreach(MyObj obj in list) { obj.Name = 5; } } class MyObj { public int Name { get; set; } } Obviamente, esta es una versión simplificada del código real que estaba escribiendo. Esto se parece mucho más a un comportamiento con el que me he topado con una propiedad que instancia una nueva instancia de un objeto. Aquí entiendo por qué obtendría una nueva instancia cada vez que hago referencia a Mine .
public MyObj Mine => new MyObj();Me sorprendió mucho ver este comportamiento en el código anterior, donde se siente más como si hubiera "bloqueado" los objetos enumerados. ¿Alguien puede ayudarme a entender esto?
Select produce un objeto que tiene una evaluación diferida . Esto significa que todos los pasos se ejecutan bajo demanda.
Entonces, cuando esta línea se ejecuta:
IEnumerable<MyObj> list = Enumerable.Range(0, 3).Select(x => new MyObj { Name = 7 }); aún no se ha creado ninguna instancia MyObj , solo el enumerable que tiene toda la información para calcular lo que ha indicado.
Cuando llama a Alter , esto se ejecuta durante la iteración a través de foreach y todos los objetos obtienen 5 asignados a sus propiedades.
Pero cuando lo imprimes, todo se vuelve a ejecutar aquí:
Console.WriteLine(string.Join(',',list.Select(x => x.Name.ToString()))); Entonces, durante la ejecución de string.Join , se crean nuevas instancias de MyObj con new MyObj { Name = 7 } y se imprimen.