Linq VS手表在当地关闭柜台的结果不同 [英] Linq Where local counter closure different results in VS watch

查看:73
本文介绍了Linq VS手表在当地关闭柜台的结果不同的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试使用LinQ Where扩展功能删除array中的前3个元素.

I try to delete first 3 elements in array with LinQ Where extension function.

这里是一个例子:

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 }结果.

It works fine and in each case i have { 4, 5, 6, 7, 8, 9 } result in console.

但是在Visual Studio 2015更新中的的问题中在test2test3情况下为3,我的结果是错误的:

But in watch in Visual Studio 2015 Update 3 in test2 and test3 case I have wrong result:

有人可以解释为什么我使用.ToList().ToArray()时一切正常,而在其他情况下却出错了吗?

Can anyone explain why everything is ok when I use .ToList() and .ToArray() and wrong in other cases?

那是虫子吗?

推荐答案

差异是由于延迟执行lambda带来的副作用.您必须在这里非常小心,因为每次枚举由Where生成的IEnumerable<T>时都会对lambda进行评估,从而导致其副作用(即递增deletedTestX)一次又一次.

The difference is due to deferred execution of the lambda with side effects. You have to be very careful here, because the lambda is evaluated each time that IEnumerable<T> produced by Where gets enumerated, causing its side effects (i.e. incrementing deletedTestX) again and again.

运行该程序时,四个序列中的每个序列均被精确枚举一次.对于情况1和4,枚举发生在ToListToArray内部,而对于情况2和3,其枚举发生在string.Join内部.

When you run the program, each of your four sequences is enumerated exactly once. For cases 1 and 4 the enumeration happens inside ToList and ToArray, while for cases 2 and 3 it happens inside string.Join.

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

When you open the results in the debugger, the controller of the watch window must run your enumeration in order to show you the results. This is the second enumeration of your sequence, so it happens with side effects of the first enumeration already applied. That's why you see wrong indexes in the debug window.

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

You can reproduce this behavior in your program by printing each result twice:

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

演示.

这篇关于Linq VS手表在当地关闭柜台的结果不同的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆