C#中的閉包和意想不到的坑

雖然閉包主要是函數式編程的玩意兒,而C#的最主要特征是面向對象,但是利用委托或lambda表達式,C#也可以寫出具有函數式編程風味的代碼。同樣的,使用委托或者lambda表達式,也可以在C#中使用閉包。

根據WIKI的定義,閉包又稱語法閉包或函數閉包,是在函數式編程語言中實現語法綁定的一種技術。閉包在實現上是一個結構體,它存儲了一個函數(通常是其入口地址)和一個關聯的環境(相當于一個符號查找表)。閉包也可以延遲變量的生存周期。

嗯。。看定義好像有點迷糊,讓我們看看下面的例子吧

e394849fedc5f0f64e51a0df347aad29.png

這個例子非常簡單,用lambda表達式創建一個Action對象,之后再調用這個Action對象。但是仔細觀察會發現,當Action對象被調用的時候,CreateGreeting方法已經返回了,作為它的實參的message應該已經被銷毀了,那么為什么我們在調用Action對象的時候,還是能夠得到正確的結果呢?

原來奧秘就在于,這里形成了閉包。雖然CreateGreeting已經返回了,但是它的局部變量被返回的lambda表達式所捕獲,延遲了其生命周期。怎么樣,這樣再回頭看閉包定義,是不是更清楚了一些?

閉包就是這么簡單,其實我們經常都在使用,只是有時候我們都不自知而已。比如大家肯定都寫過類似下面的代碼。

e4d3133271115cc05b862cf84a0d46b5.png

這里的代碼其實就用了閉包,因為我們可以肯定,在control被點擊的時候,這個message早就超過了它的聲明周期。合理使用閉包,可以確保我們寫出在空間和時間上面解耦的委托。

不過在使用閉包的時候,要注意一個陷阱。因為閉包會延遲局部變量的生命周期,在某些情況下程序產生的結果會和預想的不一樣。讓我們看看下面的例子。

a7123fcb8e3c793ae4ee8c16964e5c94.png

這個例子也非常簡單,創建一個Action鏈表并依次執行它們。看看結果

0f06783bf4b97ea524927860f83e6081.png7e3d7330467ba391e93d27886386a4f4.png

相信很多人看到這個結果的表情是這樣的!!難道不應該是0,1,2,3,4嗎?出了什么問題?

刨根問底,這兒的問題還是出現在閉包的本質上面,作為“閉包延遲了變量的生命周期”這個硬幣的另外一面,是一個變量可能在不經意間被多個閉包所引用。

在這個例子里面,局部變量i同時被5個閉包引用,這5個閉包共享i,所以最后他們打印出來的值是一樣的,都是i最后退出循環時候的值5。

要想解決這個問題也很簡單,多聲明一個局部變量,讓各個閉包引用自己的局部變量就可以了。? ??

8af2b91cca40505b696407f00ee0a864.png

d951169095c051e17b12c7f18a49dd71.png

這樣各個閉包引用不同的局部變量,剛剛的問題就解決了。

除此之外,還有一個修復的方法,在創建閉包的時候,使用foreach而不是for。至少在C# 7.0 的版本上面,這個問題已經被注意到了,使用foreach的時候編譯器會自動生成代碼繞過這個閉包陷阱。

06d6467016fbe080c728b33bed80763c.png

這就是在閉包在C#中的使用和其使用中的一個小陷阱,希望大家能通過老胡的文章了解到這個知識點并且在開發中少走彎路!

5454a2a33f3fe6ef18198a4dd0ab9ab6.gif

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/285978.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/285978.shtml
英文地址,請注明出處:http://en.pswp.cn/news/285978.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

C語言試題五十八之請編寫函數fun,:計算并輸出下列多項式的值(sn=1+1/1!+1/2!+1/3!+1/4!+…+1/n! )

??個人主頁:個人主頁 ??系列專欄:C語言試題200例目錄 ??推薦一款刷算法、筆試、面經、拿大公司offer神器 ?? 點擊跳轉進入網站 ?作者簡介:大家好,我是碼莎拉蒂,CSDN博客專家(全站排名Top 50),阿里云博客專家、51CTO博客專家、華為云享專家 1、題目 請編寫函數…

投票彰顯電信合約機諾基亞Lumia 800C受熱捧

49元可以做什么?與朋友吃頓便飯、買幾包好煙,同時也能參加中國電信Lumia 800C的合約購機計劃,其中選擇49元是最低套餐,選擇并預存600元話費,便可以以2999元購買Lumia 800C。 對于Lumia 800C,它可是新一代諾…

07查詢表達式 及 page分頁、order 排序《ThinkPHP6 入門到電商實戰》

文章目錄(更新中…) 01 thinkphp6的前期開發準備《ThinkPHP6 入門到電商實戰》 02 控制器《ThinkPHP6 入門到電商實戰》 03 數據庫查詢、模型查詢、多庫查詢《ThinkPHP6 入門到電商實戰》 04 tp6 的查數據《ThinkPHP6 入門到電商實戰》 05 tp6 的數據添…

msSql 利用 xp_cmdshell 刪除 創建目錄

DECLARE DATABakPath VARCHAR(500) ND:\DataBak\ DECLARE RemoteComand VARCHAR(500)SET RemoteComand rd /s /qDATABakPath\dbname EXEC xp_cmdshell RemoteComand,no_output --刪除文件夾,為了清理舊備份 SET RemoteComand mkdir DATABakPath\dbname EXEC xp_…

基于netty的微服務架構

基于netty的微服務架構 微服務一篇好文章 http://san-yun.iteye.com/blog/1693759 教程 http://udn.yyuap.com/doc/essential-netty-in-action/GETTING%20STARTED/Introducing%20Netty.html netty原理 http://www.infoq.com/cn/articles/netty-server-create netty方面專家 李林…

C語言試題五十九之請編寫一個函數fun,它的功能時:求fibonacci數列中大于t的最小的一個數,結果由函數返回。

??個人主頁:個人主頁 ??系列專欄:C語言試題200例目錄 ??推薦一款刷算法、筆試、面經、拿大公司offer神器 ?? 點擊跳轉進入網站 ?作者簡介:大家好,我是碼莎拉蒂,CSDN博客專家(全站排名Top 50),阿里云博客專家、51CTO博客專家、華為云享專家 1、題目 請編寫一個…

無人機模擬操控鳳凰模擬器(PhoenixRC 5.0)安裝及配置圖文教程(附鳳凰模擬器下載地址)

文章目錄 1. 鳳凰模擬器簡介2. 鳳凰模擬器安裝及配置圖文教程3. 鳳凰模擬器下載地址1. 鳳凰模擬器簡介 鳳凰phoenixrc模擬器(航模8合1模擬器)是一款專業的飛行模擬器軟件,它是屬于航模新手練模擬專用,可模擬大疆無人機,各種穿越機,還有很多固定翼和直升機等等。鳳凰模擬操…

NCF 的Dapr應用實例的運行

簡介在進行今天的主要內容之前,先帶大家了解一下DaprDapr 是一個可移植的、事件驅動的運行時,它使任何開發人員都可以輕松構建在云和邊緣上運行的彈性、無狀態和有狀態的應用程序,并包含語言和開發人員框架的多樣性。任何語言,任何…

E-MapReduce上如何升級EMR-Core

本文檔將介紹如何將老集群的EMR-Core升級到最新版本 什么是EMR-Core EMR-Core是E-MapReduce集群上支持Hadoop生態組件讀寫OSS的依賴包。它提供一種高效地讀寫OSS數據的實現,并不斷地在優化。所以,隨著E-MapReduce版本的迭代,我們就有必要升級…

06 tp6 的數據更新(改)及刪除 《ThinkPHP6 入門到電商實戰》

文章目錄(更新中…) 01 thinkphp6的前期開發準備《ThinkPHP6 入門到電商實戰》 02 控制器《ThinkPHP6 入門到電商實戰》 03 數據庫查詢、模型查詢、多庫查詢《ThinkPHP6 入門到電商實戰》 04 tp6 的查數據《ThinkPHP6 入門到電商實戰》 05 tp6 的數據添…

研發項目成本計算方法以及工作量評估

目錄 研發成本計算方法 1.1開發工作量 1.1.1估算工作量經驗值(以A來表示) 1.1.2風險系數(以σ來表示) 1.1.3復用系數(以τ來表示) 1.2開發費用 (/人月) 1.2.1 P(人頭費&#xff0…

2020年:風雨兼程,不負韶華,注定是不平凡的一年

時光易逝,歲月不老。2020,發生了太多的驚喜。 文章目錄小瑤瑤報到疫情防控,我們是認真的感謝CSDN一路相伴小瑤瑤報到 1月20日,閨女小瑤瑤已超過預產期一周了,決定入院進行手術,次日,手術順利進…

C語言試題六十之請編寫函數fun,計算并輸出下列級數和:s=1/1*2+1/2*3+…+1/n(n+1)

??個人主頁:個人主頁 ??系列專欄:C語言試題200例目錄 ??推薦一款刷算法、筆試、面經、拿大公司offer神器 ?? 點擊跳轉進入網站 ?作者簡介:大家好,我是碼莎拉蒂,CSDN博客專家(全站排名Top 50),阿里云博客專家、51CTO博客專家、華為云享專家 1、題目 編寫函數f…

Python對文件的操作(轉)

一、文件對象 我理解的文件對象就是一個接口&#xff0c;通過這個接口對文件進行相關操作。 《Python 核心編程》上說的很晦澀&#xff0c;這里沒有深刻理解到&#xff0c;希望有人能解釋給我聽。>>> f open(demo.txt,r) >>> f <open file demo.txt, mod…

微軟發布全新Win11 輕量級系統Validation OS

你可能還不知道&#xff0c;在沒有任何公開宣傳的情況下&#xff0c;在最近&#xff0c;微軟最近發布了一個全新的操作系統 Microsoft Validation OS。根據微軟的說法&#xff0c;這是一個輕量級、快速且可自定義的基于 Windows 11 的操作系統。專門為硬件或軟件供應商、開發人…

夢回編程- 由LD_LIBRARY_PATH引發JNI的理解

前些天在配置通過OCI的方式連接Oracle中曾進碰到一個關于“java.lang.UnsatisfiedLinkError: no XXX in java.library.path”這么一個問題&#xff0c;這個問題糾結了許久才解決&#xff0c;解決方式參考前面的文章。趁雙休日好好的理解一下產生這個問題的來龍去脈。先看一段話…

CSDN博客文章閱讀模式插件(附源碼)

插件地址&#xff1a;https://greasyfork.org/zh-CN/scripts/380667-csdn%E5%8D%9A%E5%AE%A2%E9%98%85%E8%AF%BB%E6%A8%A1%E5%BC%8F%E5%88%87%E6%8D%A2%E6%8F%92%E4%BB%B6 插件安裝使用說明請參閱&#xff1a;https://greasyfork.org/zh-CN 瀏覽器&#xff08;正常&#xff09…

C語言試題六十一之請編寫函數fun:將s所指字符串中下標為偶數的字符刪除,串中剩余字符形成新串放在t所指數組中。

??個人主頁:個人主頁 ??系列專欄:C語言試題200例目錄 ??推薦一款刷算法、筆試、面經、拿大公司offer神器 ?? 點擊跳轉進入網站 ?作者簡介:大家好,我是碼莎拉蒂,CSDN博客專家(全站排名Top 50),阿里云博客專家、51CTO博客專家、華為云享專家 1、題目 請編寫函數…

【ArcGIS風暴】ArcGIS tif轉jpg:JPEG壓縮僅支持8位或16位無符號數據(具有一個或三個波段,且沒有色彩映射表)解決方案!

擴展閱讀:【ArcGIS風暴】ArcGIS支持的柵格數據格式大全及格式轉換案例精解 文章目錄 問題描述tif格式和JPEG格式詳解ArcGIS軟件tif轉jpg方法總結問題描述 如下圖所示,在ArcGIS中將tif格式的無人機影像數據導出為Jpg格式時,提示:JPEG壓縮僅支持8位或16位無符號數據(具有一…

CF374 Maxim and Array

貪心 如果有0先變成非0 如果負數的個數 應該變為偶數 之后就是每次將絕對值最小的值加K #include<bits/stdc.h> using namespace std; const int MAXN 2e55; typedef long long ll;int N,K,X; ll A[MAXN]; int tag[MAXN]; struct Node{ll x; int id;Node(ll a0, int …