国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

[點滴系列][1]:從閉包說起

2019-11-17 03:06:13
字體:
來源:轉載
供稿:網友

[點滴系列][1]:從閉包說起

  世界杯車輪戰開始了,連通三天,基本進入世界杯狀態??辞蛞膊荒芡送婕夹g,這次打算把接觸c#以來的點滴總結起來,讓原本模糊的概念清晰起來,博友們一起來吧!

  [閉包]接觸這個詞的第一感覺就是晦澀難懂,下面我們就來啃一啃。

一、邂逅[閉包]

  第一次接觸閉包是在js里,先來看代碼段[1]:

1 function a() { 2     var i = 0; 3     function b() { 4         alert(++i); 5     } 6     return b; 7 } 8 var c = a(); 9 c(); 
js的閉包

  很簡單的代碼,細心觀察會發現變量i的作用域是在方法a中,也就是說出了方法a后變量i就不起作用了,可代碼中的i依然活躍在方法c中,是不是違背了程序的基本規則呢?球出界了隊員還在踢。

二、直面[閉包]

  先來啃啃[閉包]的正經概念,[閉包(Closure)]就是引用了自由變量的表達式,通常是函數(也就是代碼段[1]中的函數b)。它的特點是被引用的自由變量將和這個函數一同存在,即使已經離開了創造它的環境也不例外,通俗的講就是大家常說的閉包延長了變量的生命期。對照代碼段[1],清晰些了嗎?

  下面來看c#版的,代碼段[2]:

 1     public class PRogram 2     { 3         public static Action funcB() 4         { 5             Console.WriteLine("funcB Begin.."); 6             int i = 0; 7             i++; 8             Console.WriteLine("funcB:" + i); 9             Action action = () =>10             {11                 Console.WriteLine("funcA:" + i);12             };13             i = 100;14             Console.WriteLine("funcB:" + i);15             Console.WriteLine("funcB End..");16             return action;17         }18         static void Main()19         {20             var action = funcB();21             action();22             Console.ReadKey();23         }24     }
c#的閉包 寫法1

 1     public class Program 2     { 3         public static async Task funcA(Action callback) 4         { 5             //停留5秒,緩下節奏 6             await Task.Delay(5000); 7             Console.WriteLine("funcA continue.."); 8             callback(); 9         }10         public static void funcB()11         {12             Console.WriteLine("funcB Begin..");13             int i = 0;14             i++;15             Console.WriteLine("funcB:" + i);16             funcA(() =>17             {18                 Console.WriteLine("funcA:" + i);19             });20             i = 100;21             Console.WriteLine("funcB:" + i);22         }23         static void Main()24         {25             funcB();26             Console.WriteLine("funcB End..");27             Console.ReadKey();28         }29     }
c#的閉包 寫法2

  兩個寫法目的一樣,就是想勾起大家的所有疑問。代碼段[2]的運行結果是什么呢?為什么是這樣的結果呢?[閉包]真的延長了變量的生命期嗎?相信熟悉的人是清楚的,我們要做的是繼續深挖。

三、深挖[閉包]

  我們都懂這只是語法糖,它并沒有違背程序的基本規律。下面就抄家伙(.NET Reflector)來窺窺究竟。

圖[1] 圖[2]

圖[3]

圖[4]

圖[5]

一下上了5張圖,不要慌,慢慢來。

圖[1]是Reflector中Program類的字段、方法、類等的名稱列表。我們注意到,除去我們代碼中定義的,編譯器還自動生成了一個類:c__DisplayClass1 ?。?/p>

圖[2]是編譯器自動生成的類c__DisplayClass1中的一個方法<funcB>b__0的定義,其實就是funcB方法中的那個匿名函數 ()=>{Console.WriteLine("funcA:" + i);} 的實現;

圖[3]是編譯器自動生成的類c__DisplayClass1的實現的IL代碼,請注意方法<funcB>b__0和公共變量i

圖[4]、圖[5]是funB方法的IL代碼,每一段代表的啥意思我都大概做了標注??梢钥吹剑涸诜椒ǖ囊婚_始,編譯器就初始化了c__DisplayClass1類的一個實例,之后對于變量i的操作,在IL中其實就是對于起初初始化的那個全局的c__DisplayClass1類實例中的變量i的操作,所以說[閉包]延長了變量的生命期是假象,其實我們一直在操作一個全局的類實例的變量。

四、模仿[閉包]

  原理基本清楚了,下面我們來自己動手模仿一下編譯器做的事。

  代碼段[3]:

 1     public class Program 2     { 3         //定義一個全局的c__DisplayClass1類型的變量。 4         static c__DisplayClass1 displayCls; 5         /// <summary> 6         /// 這就是類似于編譯器的那個自定義類<>c__DisplayClass1 7         /// </summary> 8         sealed class c__DisplayClass1 9         {10             public int i;11 12             public void b_0()13             {14                 Console.WriteLine("funcA:" + i);15             }16         }17         public static Action funcB()18         {19             displayCls = new c__DisplayClass1();20             Console.WriteLine("funcB Begin..");21             displayCls.i = 0;22             displayCls.i++;23             Console.WriteLine("funcB:" + displayCls.i);24             Action action = displayCls.b_0;25             displayCls.i = 100;26             Console.WriteLine("funcB:" + displayCls.i);27             Console.WriteLine("funcB End..");28             return action;29         }30         static void Main()31         {32             var action = funcB();33             action();34             Console.ReadKey();35         }36     }
類似閉包

  編譯器費盡心思給我們做了一個語法糖,讓我們的編程更加輕松優雅。

五、終極想象

  只上代碼,代碼段[4]:

 1     public class Program 2     { 3         public static List<Action> funcB() 4         { 5             List<Action> list = new List<Action>(); 6             Console.WriteLine("funcB Begin.."); 7             int i = 0; 8             i++; 9             Console.WriteLine("funcB:" + i);10             Action action1 = () =>11             {12                 Console.WriteLine("funcA:" + i);13                 i = 200;14             };15             Action action2 = () =>16             {17                Console.WriteLine("funcA:" + i);18             };19             i = 100;20             Console.WriteLine("funcB:" + i);21             Console.WriteLine("funcB End..");22             list.Add(action1);23             list.Add(action2);24             return list;25         }26         static void Main()27         {28             var action = funcB();29             action[0]();30             action[1]();31             Console.ReadKey();32         }33     }
終極測試

  運行結果是什么呢?自己動手,豐衣足食。

  就到這兒吧,有問題的地方希望各位指正,敬禮!

  


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 肃北| 西宁市| 鱼台县| 化州市| 苏州市| 乌兰浩特市| 博野县| 波密县| 正镶白旗| 禄丰县| 修文县| 江达县| 台北市| 台中市| 潢川县| 铜山县| 当雄县| 红原县| 兴国县| 东乡族自治县| 永春县| 佳木斯市| 花莲县| 文登市| 宣威市| 合肥市| 梅州市| 石门县| 苍梧县| 梓潼县| 重庆市| 十堰市| 阿尔山市| 民乐县| 临夏县| 富裕县| 安康市| 深圳市| 安西县| 普安县| 库尔勒市|