【问题标题】:Linq Where local counter closure different results in VS watchLinq where local counter 关闭在 VS watch 中的不同结果
【发布时间】:2017-08-13 03:22:37
【问题描述】:

我尝试使用 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() 时一切正常,而在其他情况下却错了?

这是错误吗?

【问题讨论】:

  • 使用ToList()ToArray(),您可以将数据具体化为列表/数组。其他的是IEnumerable,它们有效地承诺运行数据并且您运行它们两次,一次在Console.WriteLine 中,一次在您在调试器中查看它们时。没有错误。

标签: watch c# linq visual-studio-2015 closures visual-studio-debugging


【解决方案1】:

差异是由于 lambda 的延迟执行具有副作用。此处必须非常小心,因为每次枚举由 Where 生成的 IEnumerable<T> 时都会评估 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)}}}");

Demo.

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-03-04
    • 1970-01-01
    • 2019-05-20
    • 1970-01-01
    • 2021-10-20
    • 2018-02-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多