Questa è una trappola nota per le persone che si stanno bagnando i piedi usando 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à "False", perché per ogni nome fornito per creare la collezione originale, la funzione di selezione continua a essere rivalutata e l'oggetto Record
risultante viene creato di nuovo. Per risolvere il problema, è possibile aggiungere una semplice chiamata a ToList
alla fine di GenerateRecords
.
Quale vantaggio sperava di ottenere Microsoft implementandolo in questo modo?
Perché l'implementazione non memorizza semplicemente i risultati in un array interno? Una parte specifica di ciò che sta accadendo potrebbe essere un'esecuzione posticipata, ma potrebbe comunque essere implementata senza questo comportamento.
Una volta valutato un membro di una raccolta restituito da LINQ, quale vantaggio viene fornito dal fatto di non mantenere un riferimento / una copia interna, ma invece di ricalcolare lo stesso risultato, come comportamento predefinito?
In situazioni in cui c'è una particolare necessità nella logica per lo stesso membro di una raccolta ricalcolata ripetutamente, sembra che possa essere specificato attraverso un parametro opzionale e che il comportamento predefinito potrebbe fare diversamente. Inoltre, il vantaggio di velocità ottenuto dall'esecuzione posticipata è in definitiva ridotto rispetto al 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 in definitiva nel programma di chiunque.
Che vantaggio c'è in questo, e perché Microsoft ha preso questa decisione apparentemente molto deliberata?