天坑,这样一个lambda随机取数据也有Bug

前几天,一位网友跟我说他编写的一段很简单的代码遇到了奇怪的Bug,他要达到的效果是从一个List中随机取出来一条数据,代码如下:

var random = new Random();
var users = Enumerable.Range(0, 10).Select(p => new User(p, "A" + p)).ToList();
var user = users.Find(p => p.Id == random.Next(0, 10));
Debug.Assert(user != null);record User(int Id,string Name);

2行代码生成了一个包含10User对象的List,这些UserId值从0递增到9;第3行代码中调用ListFind方法来根据lambda表达式来查找一条数据,这里通过random.Next()来获取一个[0,10)之间的随机数,然后用这个随机数来和Id进行比较。按照逻辑来讲,Find一定可以找到一条数据,所以在第4行代码中断言user一定不为null。但是这段代码有的时候运行正常,有的时候则会断言失败,从而程序抛出异常,令人不解。

当然,他的这段代码写的过于复杂,其实改成users[random.Next(0, 10)]就简单又高效。但是为了揭示问题的本质,我这里继续分析为什么用Find+lambda方法会出现问题。

我们查看一下Find方法的源代码,如下:

public T? Find(Predicate<T> match)
{for (int i = 0; i < _size; i++){if (match(_items[i]))//注意这里{return _items[i];}}return default;
}

Find方法的逻辑很简单,就是遍历List中的数据,对于每条数据都调用match这个委托来判断当前这条数据是否满足条件,如果找到一条满足条件的数据,就把它返回。如果走到最后都没有找到,就返回默认值(比如null)。这个逻辑简单到貌似看不到任何问题。

问题的关键就在if (match(_items[i]))这一句代码。它是在每一次循环都调用一下match的委托来判断当前数据的匹配性。而match指向的委托的方法体是p => p.Id == random.Next(0, 10),也就是每次匹配判断都要获取一个新的随机数来进行比较。假设在循环的时候生成的10个随机数为:9,8,8,7,9,1,1,2,3,4,那么就会每次match(_items[i])判断的结果都为false,从而导致最后返回null,也就是找不到任何的数据。

明白了原理之后,解决这个问题的思路就是不要在lambda中生成待比较的随机数,而是提前生成随机数,代码如下:

int randId = random.Next(0, 10);
var user = users.Find(p => p.Id == randId);

同样的原理也适用于Single()Where()LINQ操作。在这些操作中也要避免在lambda表达式中再进行复杂的计算,这样不仅可以避免类似这篇文章中提到的bug,而且可以提升程序的运行效率。

欢迎阅读我编写的《ASP.NET Core技术内幕与项目实战》,这本书的宗旨就是讲微软文档中没有的内容,讲原理、讲实践、讲架构

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/280507.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

中兴面试一个星期没有回音_如何在没有回声的情况下从亚马逊获取即时时尚建议...

中兴面试一个星期没有回音The Echo Look is a new device from Amazon that’s able to take a look at your outfits and tell you which one looks the best on you. However, you actually don’t need the Echo Look to get this kind of instant fashion advice from Amaz…

table分页的简单实现逻辑

为什么80%的码农都做不了架构师&#xff1f;>>> //table分页函数showPageNum: function(pageNum, allPageNum) { //pageNum点击第几页&#xff0c;allPageNum总页数$(".c_page .c_page_list").children().remove();for(var i1;i<allPageNum;i){var p…

django22:复制网页与css/时区设置

复制网页 1.复制文章 右击——检测——选中——复制——copy outerhtml (整体html) 2.复制点赞点踩 a.复制html b.css也要复制 如果是模板&#xff0c;在html head内 {% block css %}{% endblock %} 网页 {% block css %}<style>#div_digg {float: right;margin-…

Cocos Creator Ui系统

为什么80%的码农都做不了架构师&#xff1f;>>> 游戏场景&#xff1a;开发时组织游戏内容的中心&#xff1b;其中渲染根节点Canvas&#xff0c;包括属性 Design Resolution&#xff08;设计分辨率&#xff09; fit width,fit height 设计分辨率是内容生产者在制作场…

关于spring boot多张表建立外健的讨论

现在有四张表&#xff1a;student(学生表)、blogs(博客表)、comment(评论表)、reply(回复表) 现在说一下这四张表&#xff1a; student(学生表)&#xff1a;学生的信息记录表 blogs(博客表)&#xff1a;学生发表的博客表 comment(评论表)&#xff1a;学生评论博客文章的表 repl…

推荐一个使用 .NET 6 开发的开源媒体系统

你好&#xff0c;这里是 Dotnet 工具箱&#xff0c;定期分享 Dotnet 有趣&#xff0c;实用的工具和组件&#xff0c;希望对您有用&#xff01;什么是 Jellyfin ?Jellyfin 是一个免费的媒体系统&#xff0c;它可以让您更好的管理媒体&#xff0c;包括电影&#xff0c;音乐&…

亚马逊echo中国使用_如何将Amazon Echo与蓝牙扬声器配对以获得更大的声音

亚马逊echo中国使用Although both the full size Echo and the Echo Dot have respectable sound for their given sizes, compared to much bigger tabletop Bluetooth speakers (or a full home theater system with Bluetooth support), they’re pretty anemic. Let’s loo…

如何用Markdown轻松排版知乎专栏文章?

免费、便捷、高效的知乎专栏Markdown排版技巧。希望读过本文&#xff0c;可以让你的写作过程也变得更愉悦。 痛点 从前&#xff0c;写作时的排版是件辛苦事。不论你把排版环节放在写作中还是写作后&#xff0c;总会在心里清楚意识到&#xff0c;还有这么一个繁重而无趣的工作在…

Python FastApi:post文件与数据/本地端测试

FastAPI快速搭建 1 .uvicorn模块用于启动FastAPI&#xff0c;可以自定义端口&#xff0c;方便快速启动&#xff0c;特别适合pycharm启动。 2.app.post(/file/)自定义定义访问路径。 3. get_keyword_position() 内是需要输入的参数&#xff0c;包含文件和变量。普通变量建议…

德国巴伐利亚山谷积雪遍地 汽车被大雪掩埋

当地时间1月24日&#xff0c;德古南部巴伐利亚一座村庄里&#xff0c;小汽车被大雪掩埋&#xff0c;只露出一角窗户。当地时间2019年1月24日&#xff0c;德国加尔米施-帕滕基兴&#xff0c;积雪遍地。图为一名滑雪者在雪道上滑雪。当地时间2019年1月24日&#xff0c;德国加尔米…

macbook图形化编程_如何判断MacBook使用的是哪种图形芯片(并进行切换)

macbook图形化编程Apple’s top end MacBook Pros come with two graphics chips: an integrated Intel Iris Pro chip and a discrete graphics card with more power. That way, you can use the integrated chip when you need better battery life, and the more powerful …

跨集群流量调度实现 Kubernetes 集群金丝雀升级

有了多集群服务和跨集群的流量调度之后&#xff0c;使用 Kubernetes 的方式会发生很大的变化。流量的管理不再限制单一集群内&#xff0c;而是横向跨越了多个集群。最重要的是这一切“静悄悄地”发生&#xff0c;对应用来说毫无感知。就拿 Kubernetes 版本升级来说吧。记得曾经…

usr/bin/expect方式免密码登录和发送文件脚本

2019独角兽企业重金招聘Python工程师标准>>> ssh 登录 #!/usr/bin/expect set timeout 20 if { [llength $argv] < 3} { puts "Usage:" puts "remote_host password cmd" exit 1 } set remote_host [lindex $argv 0] set passwor…

8-[多线程] 进程池线程池

1、为甚需要进程池&#xff0c;线程池 介绍官网&#xff1a;https://docs.python.org/dev/library/concurrent.futures.htmlconcurrent.futures模块提供了高度封装的异步调用接口 ThreadPoolExecutor&#xff1a;线程池&#xff0c;提供异步调用 ProcessPoolExecutor: 进程池&a…

python 图像识别pytesseract快速设置

一、安装Tesseract 以window安装为例&#xff0c;参考&#xff1a;https://segmentfault.com/a/1190000014086067 note&#xff1a; 使用虚拟环境需要&#xff1a; 在 python 环境&#xff08;或虚拟环境&#xff09; \Lib\site-packages\pytesseract 目录下找到 pytessera…

香港连续25年被评为全球最自由经济体

中新社香港1月25日电 美国智库传统基金会25日在华盛顿发表2019年《经济自由度指数》报告&#xff0c;香港今年再次成为唯一一个总分超过90分的经济体&#xff0c;已连续25年被评价为全球最自由经济体。 报告显示&#xff0c;香港今年的总分为90.2分&#xff08;100分为满分&…

mac 下安装jenkins

2019独角兽企业重金招聘Python工程师标准>>> 平台搭建 Jenkins安装和启动 官网&#xff1a;https://jenkins.io/index.html 下载&#xff1a;http://mirrors.jenkins-ci.org/war/latest/jenkins.war 安装&#xff1a; 依赖于Java环境&#xff0c;首先安装和配置Java…

safari 获取视频流_如何在Safari中将RSS feed和社交媒体合并为一个流

safari 获取视频流Safari allows you to subscribe to RSS feeds and add your social media accounts so you can view them right in the browser, in one universal feed, without the need of any add-on applications or extensions. Safari允许您订阅RSS feed并添加您的社…

pytesseract:opencv预处理图片

一、目的 原始图片用pytesseract识别文字&#xff0c;精准度往往没达到预期。使用opencv处理后&#xff0c;提高识别精准度。处理方法有 a.图片转成白底黑字。 b.截取图片某固定区域。这个很重要&#xff0c;因为图片包含图标或其他形状图形&#xff0c;辨识导致错乱的。 二…

编译安装Centos7.2+Apache2.4.25+PHP7.2.10+Mysql5.6.16

一、编译部署Apache2.4.251、环境准备#设置或停止防火墙&#xff1a; [rootlocalhost ~]# systemctl stop firewalld.service [rootlocalhost ~]# systemctl disable firewalld.service#关闭selinux&#xff1a; 临时关闭&#xff1a; [rootlocalhost ~]# setenforce 0永久关闭…