Il s'agit d'un piège connu pour les personnes qui se mouillent les pieds avec 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;
}
}
}
Cela affichera "False", car pour chaque nom fourni pour créer la collection d'origine, la fonction de sélection continue d'être réévaluée et l' Record
objet résultant est à nouveau créé. Pour résoudre ce problème, un simple appel à ToList
pourrait être ajouté à la fin de GenerateRecords
.
Quel avantage Microsoft espérait-il gagner en l'implémentant de cette façon?
Pourquoi l'implémentation ne mettrait-elle pas simplement en cache les résultats d'un tableau interne? Une partie spécifique de ce qui se passe peut être l'exécution différée, mais cela pourrait toujours être implémenté sans ce comportement.
Une fois qu'un membre donné d'une collection retourné par LINQ a été évalué, quel avantage offre de ne pas conserver une référence / copie interne, mais de recalculer le même résultat, comme comportement par défaut?
Dans les situations où il existe un besoin particulier dans la logique pour le même membre d'une collection recalculé encore et encore, il semble que cela pourrait être spécifié via un paramètre facultatif et que le comportement par défaut pourrait faire autrement. De plus, l'avantage de vitesse qui est gagné par l'exécution différée est finalement réduit par le temps qu'il faut pour recalculer continuellement les mêmes résultats. Enfin, c'est un bloc déroutant pour ceux qui sont nouveaux dans LINQ, et cela pourrait conduire à des bugs subtils dans le programme de n'importe qui.
Quel avantage y a-t-il et pourquoi Microsoft a-t-il pris cette décision apparemment très délibérée?
return listOfNames.Select(x => new Record(Guid.NewGuid(), x)).ToList();
Cela vous donne votre "copie en cache". Problème résolu.