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 }
结果在控制台 。
但是在test2
和test3
中的Visual Studio 2015 Update 3中观察我的结果有误:
当我使用.ToList()
和.ToArray()
以及其他情况下的错误时,有人可以解释为什么一切正常吗?
那个错误吗?
差异是由于延迟执行具有副作用的lambda。 在这里你必须非常小心,因为每当被枚举的Where
产生的IEnumerable
评估lambda时,会一次又一次地导致其副作用(即递增deletedTestX
)。
运行程序时,您的四个序列中的每一个都只列举一次。 对于情况1和4,枚举发生在ToList
和ToArray
,而对于情况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)}}}");
演示。