c# – LINQ投影(选择)返回奇数结果
请考虑以下代码
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(); } } } 重现步骤 >在Console.Read()上放置一个断点 问题 鉴于我仅从值1中获取了50个项目,我期望计数显示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(); } } } 例 检查次数 检查值2(填充结果视图) 检查次数 关于这里发生了什么的解释,以及如何解决? 注意 许多给定的答案表明延期执行.我知道linq使用延期执行,所以除非我错过了一些事情,这不是问题. 我的观点是当断点被击中时,CLR已创建一个状态机为值2.然后在调试器中迭代,计数立即增加到100,看来只有1次迭代.这似乎有点奇怪! 此外,我知道随后的值2的结果视图的人口数量增加,因为这导致状态机的进一步迭代. 解决方法
每次检查值2时,表达式将再次进行评估,如果您在监视窗口中检查该表达式,则每次都会进行两次评估(不要问我为什么;询问编写监视窗口代码的人员).我得到了count == 300.每当有一些评估它,它增加50计数;这就是代码所做的,看看你自己.并且每次在观察窗口中展开它,计数增加100.所以,观察窗口评估它两次.
你只看到那些时代,但是呢?许多东西都在VS代码里面,它不麻烦给你看. GUI不是进入程序内部的窗口;屏幕上有一些像素,一些代码有意识地着色.我可以编写一个监视窗口,评估表达十九次,并显示一个口袋妖怪.什么是更合理的解释:你从未见过的一些代码是做一些不会在GUI中显示的东西,或者有时您的计算机无法添加? 查看值2的运行时类型: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(); 现在count == 50,因为表达式只被评估一次,结果存储在List< T>中. 故事的道德启示: 屏幕上的点是幻觉,结合懒惰评估与副作用就像用机枪在星巴克放松猴子.我不是说这是错的,只是不是每个人都有一个有趣的日子. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |