La différence est due à l'exécution différée du lambda avec des effets secondaires. Vous devez être très prudent ici, car le lambda est évalué chaque fois que IEnumerable<T>
produit par Where
est énuméré, causant ses effets secondaires (c'est-à-dire incrémentant deletedTestX
) encore et encore. Lorsque vous exécutez le programme, chacune de vos quatre séquences est énumérée une fois exactement. Pour les cas 1 et 4 l'énumération se passe à l'intérieur de ToList
et ToArray
, alors que pour les cas 2 et 3 cela se passe à l'intérieur de string.Join
.
Lorsque vous ouvrez les résultats dans le débogueur, le contrôleur de la fenêtre de surveillance doit exécuter votre énumération afin de vous montrer les résultats. C'est la deuxième énumération de votre séquence, donc cela arrive avec les effets secondaires de la première énumération déjà appliquée. C'est pourquoi vous voyez des index erronés dans la fenêtre de débogage.
Vous pouvez reproduire ce comportement dans votre programme en imprimant chaque résultat deux fois:
var array = new[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
var count = 3;
var deletedTest1 = 0;
var test1 = array.Where(x => ++deletedTest1 > count).ToList();
Console.WriteLine("Test 1, deletedTest1={0}", deletedTest1);
Console.WriteLine($"{{{String.Join(", ", test1)}}}");
Console.WriteLine("Test 1, deletedTest1={0}", deletedTest1);
Console.WriteLine($"{{{String.Join(", ", test1)}}}");
var deletedTest2 = 0;
var test2 = array.Where(x => ++deletedTest2 > count).AsEnumerable();
Console.WriteLine("Test 2, deletedTest2={0}", deletedTest2);
Console.WriteLine($"{{{String.Join(", ", test2)}}}");
Console.WriteLine("Test 2, deletedTest2={0}", deletedTest2);
Console.WriteLine($"{{{String.Join(", ", test2)}}}");
var deletedTest3 = 0;
var test3 = array.Where(x => ++deletedTest3 > count);
Console.WriteLine("Test 3, deletedTest3={0}", deletedTest3);
Console.WriteLine($"{{{String.Join(", ", test3)}}}");
Console.WriteLine("Test 3, deletedTest3={0}", deletedTest3);
Console.WriteLine($"{{{String.Join(", ", test3)}}}");
var deletedTest4 = 0;
var test4 = array.Where(x => ++deletedTest4 > count).ToArray();
Console.WriteLine("Test 4, deletedTest4={0}", deletedTest4);
Console.WriteLine($"{{{String.Join(", ", test4)}}}");
Console.WriteLine("Test 4, deletedTest4={0}", deletedTest4);
Console.WriteLine($"{{{String.Join(", ", test4)}}}");
Demo.
Avec 'ToList()' et 'ToArray()' vous matérialisait les données à une liste/tableau. Les autres sont 'IEnumerable' qui promettent effectivement d'exécuter les données et vous les exécutez deux fois, une fois dans' Console.WriteLine' et une fois lorsque vous les affichez dans le débogueur. Il n'y a pas de bug. – DavidG