亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

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

發布時間:2021-07-08 15:38:25 來源:億速云 閱讀:172 作者:Leah 欄目:編程語言

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

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

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

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

其中lambda表達式使用了在其外部定義的變量num。我們可以認為該段lambda語句塊構成了一個閉包,而這個閉包捕獲了外部變量num。

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

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

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

好了,我們現在可以這樣使用這個函數了:

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

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

第二行更好理解,我們執行了myFunc,并將返回結果賦值給了變量result。我們再深入思考一下:在執行myFunc的時候,會訪問到在CreateFunction中定義兩個變量str與num。

雖然這時CreateFunction的棧幀早就被銷毀了,其內部定義的變量至今也“生死不明”了,但是因為我們知道這兩個變量已經被閉包所捕獲了,所以我們堅信這兩個變量截至目前為止還是可以訪問的!

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

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

那么,我們為什么還能安全的訪問num呢?C#中的變量捕獲機制究竟有什么神奇之處,可以讓值類型擁有違反常規的生存周期呢?裝箱!你可能會立刻想到,把每個值類型都裝到一個對象里,我們就可以讓這個值類型擁有和那個包裹它的對象相同的壽命了。

不過,這并不是C#實現者所選擇的方式!C#并不會對每個需要捕獲的值類型變量進行裝箱操作,而是把所有捕獲的變量統統放到同一個大“箱子”里&mdash;&mdash;當編譯器遇到需要變量捕獲的情況時,它會默默地在后臺構造一個類型,這個類型包含了每一個閉包所捕獲的變量(包括值類型變量和引用類型變量)作為它的一個公有字段。這樣,編譯器就可以

維護那些在匿名函數或lambda表達式中出現的外部變量了。

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

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

看完上述內容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注億速云行業資訊頻道,感謝您對億速云的支持。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

新绛县| 丹东市| 洪洞县| 孙吴县| 桂东县| 六安市| 文安县| 永平县| 山东省| 文成县| 西畴县| 新昌县| 宜城市| 贺兰县| 平和县| 汝南县| 大理市| 察隅县| 灵丘县| 鄂托克旗| 雷州市| 绵竹市| 巫溪县| 康马县| 八宿县| 周至县| 平昌县| 当阳市| 阳谷县| 视频| 大荔县| 原阳县| 四平市| 皋兰县| 洛扎县| 永丰县| 青铜峡市| 新和县| 东台市| 丹寨县| 舒兰市|