Questa è una trappola nota per le persone che si bagnano i piedi 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;
}
}
}
Questo stamperà "Falso", perché per ogni nome fornito per creare la raccolta originale, la funzione di selezione continua a essere rivalutata e l' Record
oggetto risultante viene creato di nuovo. Per risolvere questo problema, è ToList
possibile aggiungere una semplice chiamata a alla fine di GenerateRecords
.
Quale vantaggio sperava Microsoft di ottenere implementandolo in questo modo?
Perché l'implementazione non dovrebbe semplicemente memorizzare nella cache i risultati un array interno? Una parte specifica di ciò che sta accadendo potrebbe essere l'esecuzione differita, ma ciò potrebbe essere comunque implementato senza questo comportamento.
Una volta valutato un determinato membro di una raccolta restituita da LINQ, quale vantaggio viene offerto non mantenendo un riferimento / copia interno, ma invece ricalcolando lo stesso risultato, come comportamento predefinito?
In situazioni in cui vi è una particolare necessità nella logica per lo stesso membro di una raccolta ricalcolata più e più volte, sembra che potrebbe essere specificato tramite un parametro opzionale e che il comportamento predefinito potrebbe fare diversamente. Inoltre, il vantaggio di velocità ottenuto dall'esecuzione differita viene infine ridotto dal tempo necessario per ricalcolare continuamente gli stessi risultati. Infine, questo è un blocco confuso per coloro che sono nuovi a LINQ e potrebbe portare a bug sottili nel programma di chiunque.
Qual è il vantaggio di questo, e perché Microsoft ha preso questa decisione apparentemente molto deliberata?
return listOfNames.Select(x => new Record(Guid.NewGuid(), x)).ToList();
Questo ti dà la tua "copia cache". Problema risolto.