色婷婷狠狠18禁久久YY,CHINESE性内射高清国产,国产女人18毛片水真多1,国产AV在线观看

理解閉包是如何與變量作用域相互影響的?

閉包的概念:

內(nèi)層的函數(shù)可以引用包含在它外層的函數(shù)的變量,即使外層函數(shù)的執(zhí)行已經(jīng)終止。但該變量提供的值并非變量創(chuàng)建時(shí)的值,而是在父函數(shù)范圍內(nèi)的最終值。

要理解閉包,首先要搞懂清楚是變量的作用域和生命周期。我們以C#為例:

在C#中,變量作用域有三種,一種是屬于類的,稱之為field;第二屬于函數(shù)的,我們通常稱之為局部變量;還有一種,也是屬于函數(shù)的,不過(guò)它的作用范圍更小,它只屬于函數(shù)局部的代碼片段,這種同樣稱之為局部變量。這三種變量的生命周期基本都可以用一句話來(lái)說(shuō)明,每個(gè)變量都屬于它所寄存的對(duì)象,即變量隨著其寄存對(duì)象生而生和消亡。對(duì)應(yīng)三種作用域我們可以這樣說(shuō),類里面的變量是隨著類的實(shí)例化而生,同時(shí)伴隨著類對(duì)象的資源回收而消亡(當(dāng)然這里不包括非實(shí)例化的static和const對(duì)象)。而函數(shù)(或代碼片段)的變量也隨著函數(shù)(或代碼片段)調(diào)用開(kāi)始而生,伴隨函數(shù)(或代碼片段)調(diào)用結(jié)束而自動(dòng)由GC釋放,它內(nèi)部變量生命周期滿足先進(jìn)后出的特性。在作用域以外不能對(duì)變量進(jìn)行讀寫等操作。

作用域外試圖去操作變量時(shí),提示當(dāng)前上下文不存在XXX等類似的錯(cuò)誤提示。

那么這里有沒(méi)有例外呢?答案是有的

先來(lái)看一段代碼:

變量n實(shí)際上是屬于函數(shù)T1的局部變量,它本來(lái)生命周期應(yīng)該是伴隨著函數(shù)T1的調(diào)用結(jié)束而被釋放掉的,但這里我們卻在返回的委托b中仍然能調(diào)用它,因?yàn)門1調(diào)用返回的匿名委托的代碼片段中我們用到了n,而在編譯器看來(lái),這些都是合法的,因?yàn)榉祷氐奈衎和函數(shù)T1存在上下文關(guān)系,也就是說(shuō)匿名委托b是允許使用它所在的函數(shù)或者類里面的局部變量的,于是編譯器通過(guò)一系列動(dòng)作(具體動(dòng)作我們后面再說(shuō))使b中調(diào)用的函數(shù)T1的局部變量自動(dòng)閉合,從而使該局部變量滿足新的作用范圍。

閉包的優(yōu)點(diǎn):

使用閉包,我們可以輕松的訪問(wèn)外層函數(shù)定義的變量,這在匿名方法中普遍使用。比如有如下場(chǎng)景,在winform應(yīng)用程序中,我們希望做這么一個(gè)效果,當(dāng)用戶關(guān)閉窗體時(shí),給用戶一個(gè)提示框。我們將添加如下代碼:
如果我們不使用匿名函數(shù),就必須用其他方式來(lái)把tipWords的值傳遞給FormClosing注冊(cè)的處理函數(shù),這就增加了不必要的代碼工作量。所以說(shuō)閉包可以極大的簡(jiǎn)化我們的代碼工作量,使我們的代碼更加優(yōu)美簡(jiǎn)潔。

閉包的陷阱:

應(yīng)用閉包,我們要注意一個(gè)陷阱。比如有一個(gè)學(xué)生信息的數(shù)組,我們需要遍歷每一個(gè)用戶,對(duì)各個(gè)用戶做處理后輸出用戶名。首先建立一個(gè)學(xué)生類,包含學(xué)生姓名和年齡

然后在主函數(shù)里聲明一組學(xué)生數(shù)組,當(dāng)然我是在winform里面的按鈕click事件注冊(cè)的函數(shù)里寫的,你也可以在別的地方。


預(yù)想的輸出應(yīng)該為:”張三”,”李四”,”王五”。

但是實(shí)際運(yùn)行中會(huì)報(bào)錯(cuò):提示索引超出界限。

為什么沒(méi)有達(dá)到我們預(yù)期的效果呢?讓我們?cè)賮?lái)看一下閉包的概念。內(nèi)層函數(shù)引用的外層函數(shù)的變量時(shí),該變量提供的值并非變量創(chuàng)建時(shí)的值,而是在父函數(shù)范圍內(nèi)的最終值。就是說(shuō),當(dāng)線程中執(zhí)行方法時(shí),方法中的i參數(shù)的值,并不是從0累加到2,而是始終是累加道德極限值,也就是3。原來(lái)如此,那我們應(yīng)該如何避免這種陷阱呢?

C#中普遍的做法是,將匿名函數(shù)引用的變量用一個(gè)臨時(shí)變量保存下來(lái),然后在匿名函數(shù)中使用臨時(shí)變量。
我們?cè)龠\(yùn)行來(lái)看,輸出依次為”張三”,”李四”,”王五”。.注意,每次的輸出順序可能不同,這是由于此處的線程執(zhí)行順序是由CPU調(diào)度的。

最后,閉包并不是針對(duì)某一特定語(yǔ)言的概念,而是一個(gè)通用的概念。除了在各個(gè)支持函數(shù)式編程的語(yǔ)言中,我們會(huì)接觸到它。一些不支持函數(shù)式編程的語(yǔ)言中也能支持閉包(如java8之前的匿名內(nèi)部類)。