Linq哪里有本地计数器关闭不同结果VS手表

我尝试使用LinQ Where扩展函数删除array前3个元素。

这是一个例子:

 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($"{{{String.Join(", ", test1)}}}"); var deletedTest2 = 0; var test2 = array.Where(x => ++deletedTest2 > count).AsEnumerable(); Console.WriteLine($"{{{String.Join(", ", test2)}}}"); var deletedTest3 = 0; var test3 = array.Where(x => ++deletedTest3 > count); Console.WriteLine($"{{{String.Join(", ", test3)}}}"); var deletedTest4 = 0; var test4 = array.Where(x => ++deletedTest4 > count).ToArray(); Console.WriteLine($"{{{String.Join(", ", test4)}}}"); 

它工作正常,在每种情况下我都有{ 4, 5, 6, 7, 8, 9 }结果在控制台

但是在test2test3中的Visual Studio 2015 Update 3中观察我的结果有误:

在此处输入图像描述

当我使用.ToList().ToArray()以及其他情况下的错误时,有人可以解释为什么一切正常吗?

那个错误吗?

差异是由于延迟执行具有副作用的lambda。 在这里你必须非常小心,因为每当被枚举的Where产生的IEnumerable评估lambda时,会一次又一次地导致其副作用(即递增deletedTestX )。

运行程序时,您的四个序列中的每一个都只列举一次。 对于情况1和4,枚举发生在ToListToArray ,而对于情况2和3,它发生在string.Join

在调试器中打开结果时,监视窗口的控制器必须运行枚举才能显示结果。 这是序列的第二个枚举,因此它已经应用了第一个枚举的副作用。 这就是你在调试窗口中看到错误索引的原因。

您可以通过两次打印每个结果在程序中重现此行为:

 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)}}}"); 

演示。