c# – LINQ投影(选择)返回奇数结果

c# – LINQ投影(选择)返回奇数结果,第1张

概述请考虑以下代码 namespace ConsoleApp1{ using System; using System.Collections.Generic; using System.Linq; public class Program { public static void Main(string[] args) { 请考虑以下代码
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()上放置一个断点
>运行到断点
>检查次数(应显示0)
>检查值2并填充“结果视图”
>检查数(应显示100)

问题

鉴于我仅从值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&gt ;.这是没有收集,这是等待执行的. 我们将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>中.

故事的道德启示:

屏幕上的点是幻觉,结合懒惰评估与副作用就像用机q在星巴克放松猴子.我不是说这是错的,只是不是每个人都有一个有趣的日子.

总结

以上是内存溢出为你收集整理的c# – LINQ投影(选择)返回奇数结果全部内容,希望文章能够帮你解决c# – LINQ投影(选择)返回奇数结果所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1261759.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-08
下一篇 2022-06-08

发表评论

登录后才能评论

评论列表(0条)

保存