请考虑以下代码
namespace ConsoleApp1
{
using System;
using System.Collections.Generic;
using System.Linq;
public class Program
{
public static void Main(string[] args)
{
int count = default(int);
IEnumerable<int> values1 = Enumerable.Range(1, 200)
.OrderBy(o => Guid.NewGuid())
.Take(100);
IEnumerable<int> values2 = values1
.OrderBy(o => Guid.NewGuid())
.Take(50)
.Select(o => { count++; return o; });
Console.Read();
}
}
}
Run Code Online (Sandbox Code Playgroud)
重现步骤
Console.Read();count++(应显示0)values2并填充结果视图count++(应显示100)问题
鉴于我只拍摄了50个项目values1,我希望count++显示50.为什么显示100个?
请注意,如果这令人困惑,请尝试运行此代码,它会产生相同的结果......
namespace ConsoleApp1
{
using System;
using System.Collections.Generic;
using System.Linq;
public class Program
{
public static void Main(string[] args)
{
int count = default(int);
IEnumerable<int> values1 = Enumerable.Range(1, 100)
.OrderBy(o => Guid.NewGuid())
.Take(50);
IEnumerable<int> values2 = values1
.OrderBy(o => Guid.NewGuid())
.Take(50)
.Select(o => { count++; return o; });
Console.Read();
}
}
}
Run Code Online (Sandbox Code Playgroud)
例
检查 count++
检查values2(填充结果视图)
检查 count++
关于这里发生了什么,以及如何解决它的任何解释?
注意
许多给出的答案表明延期执行.我知道linq使用延迟执行,所以除非我遗漏了什么,否则这不是问题.
我的观点是,当命中断点时,CLR为values2创建了一个状态机.然后在调试器中迭代,计数立即增加到100,看起来只有1次迭代.这看起来有点奇怪!
此外,我知道value2的结果视图的后续群体会导致计数增加,因为这会导致状态机的进一步迭代.
15e*_*153 17
每次检查时values2,表达式都会再次进行评估 - 如果你在监视窗口中检查它,它似乎每次都会被评估两次(不要问我原因;请问那些编写监视窗口代码的人).我有count == 300.每当某计算它,把它添加50到count; 这就是代码的作用,亲自看看.每次在监视窗口中展开它时,都会count增加100.因此,监视窗口会对其进行两次评估.
你只看到其中一个时代,但那又怎么样?很多东西都在VS代码里面进行,它没有给你看.GUI不是进入程序内部的窗口; 它是屏幕上的一堆像素,有些代码故意着色.我可以编写一个观察窗口,评估表达式十九次并向您显示一个口袋妖怪.更合理的解释是什么:你从未见过的一些代码正在做一些不会在GUI中显示的内容,或者有时你的计算机无法添加?
查看运行时类型values2:System.Linq.Enumerable.WhereSelectEnumerableIterator<int, int>.这不是集合,而是等待执行的东西.
让我们添加ToList()到该表达式的末尾.这将评估一次并存储结果.然后,您可以整天检查结果,而无需再次执行任何LINQ表达式.
int count = default(int);
IEnumerable<int> values1 = Enumerable.Range(1, 200)
.OrderBy(o => Guid.NewGuid())
.Take(100);
IEnumerable<int> values2 = values1
.OrderBy(o => Guid.NewGuid())
.Take(50)
.Select(o => { count++; return o; })
.ToList();
Run Code Online (Sandbox Code Playgroud)
现在count == 50,因为表达式只被评估一次,结果存储在一个List<T>.
屏幕上的圆点是幻觉,将懒惰的评价与副作用结合起来就像用机枪在星巴克放松猴子一样.我不是说这是错的,只是不是每个人都想到一个有趣的约会.
| 归档时间: |
|
| 查看次数: |
538 次 |
| 最近记录: |