真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

C#中怎么利用閉包捕獲變量

C#中怎么利用閉包捕獲變量,很多新手對(duì)此不是很清楚,為了幫助大家解決這個(gè)難題,下面小編將為大家詳細(xì)講解,有這方面需求的人可以來學(xué)習(xí)下,希望你能有所收獲。

陜州ssl適用于網(wǎng)站、小程序/APP、API接口等需要進(jìn)行數(shù)據(jù)傳輸應(yīng)用場(chǎng)景,ssl證書未來市場(chǎng)廣闊!成為成都創(chuàng)新互聯(lián)的ssl證書銷售渠道,可以享受市場(chǎng)價(jià)格4-6折優(yōu)惠!如果有意向歡迎電話聯(lián)系或者加微信:18980820575(備注:SSL證書合作)期待與您的合作!

簡(jiǎn)單來講,閉包允許你將一些行為封裝,將它像一個(gè)對(duì)象一樣傳來遞去,而且它依然能夠訪問到原來***次聲明時(shí)的上下文。這樣可以使控制結(jié)構(gòu)、邏輯操作等從調(diào)用細(xì)節(jié)中分離出來。訪問原來上下文的能力是閉包區(qū)別一般對(duì)象的重要特征,盡管在實(shí)現(xiàn)上只是多了一些編譯器技巧。

我們知道,在匿名方法或者lambda中,可以訪問或者修改該匿的定義范圍內(nèi)的變量。例如:

int num = 1;   Func incNum = () => ++num;

其中l(wèi)ambda表達(dá)式使用了在其外部定義的變量num。我們可以認(rèn)為該段lambda語句塊構(gòu)成了一個(gè)閉包,而這個(gè)閉包捕獲了外部變量num。

好了,不說那么多讓人看著難受的定義套話了。我們進(jìn)入正題,看看在C#中變量是如何被捕獲的。來看一個(gè)例子:

public Func CreateFunction()   {   String str = "我的幸運(yùn)數(shù)字是";   int num = 17;   Func func = () => str + num;   return func;   }

在這個(gè)例子中,定義了一個(gè)返回一個(gè)函數(shù)的方法CreateFunction。返回的函數(shù)構(gòu)成了一個(gè)閉包,該閉包捕獲了兩個(gè)變量:String類型的str和int類型的num。

好了,我們現(xiàn)在可以這樣使用這個(gè)函數(shù)了:

Func   myFunc = CreateFunction();   String result = myFunc();

我們來分析一下這兩行代碼實(shí)際都干了什么。***行很容易理解,我們把方法CreateFunction生成的匿名函數(shù)賦值給了委托myFunc。

第二行更好理解,我們執(zhí)行了myFunc,并將返回結(jié)果賦值給了變量result。我們?cè)偕钊胨伎家幌拢涸趫?zhí)行myFunc的時(shí)候,會(huì)訪問到在CreateFunction中定義兩個(gè)變量str與num。

雖然這時(shí)CreateFunction的棧幀早就被銷毀了,其內(nèi)部定義的變量至今也“生死不明”了,但是因?yàn)槲覀冎肋@兩個(gè)變量已經(jīng)被閉包所捕獲了,所以我們堅(jiān)信這兩個(gè)變量截至目前為止還是可以訪問的!

對(duì)于str對(duì)象,鑒于它是一個(gè)引用類型,所以只要有存在某個(gè)“東西”一直保存著對(duì)它的引用,它就不會(huì)被銷毀。這樣我們完全不用擔(dān)心在我們需要它時(shí),編譯器或運(yùn)行時(shí)會(huì)告訴我們它被弄丟了。

然而對(duì)于num,情況就有些不同了。num是一個(gè)值類型。我們知道值類型是存活在棧上的,我們也知道它所存在的那個(gè)棧幀(也就是CreateFunction的幀)在CreateFunction執(zhí)行完畢后就會(huì)被銷毀,然后其上存在的任何值類型也會(huì)被一并的銷毀,這其中當(dāng)然包括我們所關(guān)注的變量num了。

那么,我們?yōu)槭裁催€能安全的訪問num呢?C#中的變量捕獲機(jī)制究竟有什么神奇之處,可以讓值類型擁有違反常規(guī)的生存周期呢?裝箱!你可能會(huì)立刻想到,把每個(gè)值類型都裝到一個(gè)對(duì)象里,我們就可以讓這個(gè)值類型擁有和那個(gè)包裹它的對(duì)象相同的壽命了。

不過,這并不是C#實(shí)現(xiàn)者所選擇的方式!C#并不會(huì)對(duì)每個(gè)需要捕獲的值類型變量進(jìn)行裝箱操作,而是把所有捕獲的變量統(tǒng)統(tǒng)放到同一個(gè)大“箱子”里——當(dāng)編譯器遇到需要變量捕獲的情況時(shí),它會(huì)默默地在后臺(tái)構(gòu)造一個(gè)類型,這個(gè)類型包含了每一個(gè)閉包所捕獲的變量(包括值類型變量和引用類型變量)作為它的一個(gè)公有字段。這樣,編譯器就可以

維護(hù)那些在匿名函數(shù)或lambda表達(dá)式中出現(xiàn)的外部變量了。

更進(jìn)一步,如果我們使用ILDASM工具查看CreateFunction方法的IL代碼,我們會(huì)發(fā)現(xiàn)編譯器壓根就沒有聲明num和str變量。取而代之的是聲明了一個(gè)類型名和實(shí)例名都及其難看的包裝對(duì)象。這個(gè)玩意兒就是我們上面所說的那個(gè)被編譯器默默生成,保存了所有捕獲變量的引用的對(duì)象。

我們還可以看到,在CreateFunction方法,C#源代碼內(nèi)所有對(duì)str和num的操作,在IL中都被轉(zhuǎn)換成了對(duì)包裝對(duì)象的同名公有成員的操作。順便說一句,就連我們構(gòu)造的那個(gè)lambda表達(dá)式“() => str + num”現(xiàn)在都被編譯器轉(zhuǎn)換成了這個(gè)包裝對(duì)象的一個(gè)方法!

看完上述內(nèi)容是否對(duì)您有幫助呢?如果還想對(duì)相關(guān)知識(shí)有進(jìn)一步的了解或閱讀更多相關(guān)文章,請(qǐng)關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝您對(duì)創(chuàng)新互聯(lián)的支持。


分享名稱:C#中怎么利用閉包捕獲變量
標(biāo)題路徑:http://weahome.cn/article/goechi.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部