天坑,這樣一個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.pswp.cn/news/280507.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/280507.shtml
英文地址,請注明出處:http://en.pswp.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永久關閉…