Esta es una trampa conocida para las personas que se están mojando los pies con LINQ:
public class Program
{
public static void Main()
{
IEnumerable<Record> originalCollection = GenerateRecords(new[] {"Jesse"});
var newCollection = new List<Record>(originalCollection);
Console.WriteLine(ContainTheSameSingleObject(originalCollection, newCollection));
}
private static IEnumerable<Record> GenerateRecords(string[] listOfNames)
{
return listOfNames.Select(x => new Record(Guid.NewGuid(), x));
}
private static bool ContainTheSameSingleObject(IEnumerable<Record>
originalCollection, List<Record> newCollection)
{
return originalCollection.Count() == 1 && newCollection.Count() == 1 &&
originalCollection.Single().Id == newCollection.Single().Id;
}
private class Record
{
public Guid Id { get; }
public string SomeValue { get; }
public Record(Guid id, string someValue)
{
Id = id;
SomeValue = someValue;
}
}
}
Esto imprimirá "Falso", porque para cada nombre proporcionado para crear la colección original, la función de selección se vuelve a evaluar y el Record
objeto resultante se crea de nuevo. Para solucionar esto, ToList
se puede agregar una simple llamada a al final de GenerateRecords
.
¿Qué ventaja esperaba obtener Microsoft al implementarlo de esta manera?
¿Por qué la implementación simplemente no almacena en caché los resultados en una matriz interna? Una parte específica de lo que está sucediendo puede ser la ejecución diferida, pero eso podría implementarse sin este comportamiento.
Una vez que se ha evaluado un miembro dado de una colección devuelta por LINQ, ¿qué ventaja se proporciona al no mantener una referencia / copia interna, sino que se vuelve a calcular el mismo resultado, como un comportamiento predeterminado?
En situaciones donde hay una necesidad particular en la lógica para el mismo miembro de una colección recalculada una y otra vez, parece que eso podría especificarse a través de un parámetro opcional y que el comportamiento predeterminado podría hacerlo de otra manera. Además, la ventaja de velocidad que se obtiene con la ejecución diferida se reduce en última instancia por el tiempo que lleva recalcular continuamente los mismos resultados. Finalmente, este es un bloque confuso para aquellos que son nuevos en LINQ, y podría conducir a errores sutiles en el programa de cualquier persona.
¿Qué ventaja tiene esto y por qué Microsoft tomó esta decisión aparentemente muy deliberada?
return listOfNames.Select(x => new Record(Guid.NewGuid(), x)).ToList();
Eso te da tu "copia en caché". Problema resuelto.