參加工做以來,拜讀過不少大做。有好多書讀的時候感受大徹大悟,不自覺的發出‘哦。。。’這樣的感嘆。可是隨着殺豬刀(時間)不斷的飛逝,不只給我臉上帶來了皺紋,還帶走了很多前人總結和概括的知識點和那些我還沒來得及吸取的寶貴財富。好記性不如爛筆頭,我決定開始寫一些讀書的筆記和工做上的心得,最好是二者可以結合起來,把知識真正的本身轉化成本身的能力。程序員
下面進入正題。閉包在程序員的平常工做幾乎無所不在,固然不只是工做,面試的時候常常也會有相關的題目。看過不少博客園上的朋友都有解釋,每次重溫都有‘哦。。。’的感受。對,是每次。。。多是由於我才疏學淺的緣由吧,有些大神解釋得很深刻,最後總結的又太精闢。這幾天在重溫C#本質論(第三版)(有一個聲音飄過:你以前也沒看完過。。。。)。裏面提到了閉包,只是很小的一段,說的不算‘深刻’(沒有列出IL),可是絕對算得上淺出,這回我真的是大徹大悟,相信你看完也必須懂了。面試
爲了更好的理解代碼,須要用幾行代碼來講明一下Lamda表達式(匿名方法)的實現。和閉包同樣,它們只是編譯器玩的小把戲,爲的實讓咱們用起來更爽一點。數據結構
class Program { static void Main(string[] args) { int[] items = new int[2]; for (int i = 0; i < items.Length; i++) { Console.WriteLine("Enter a integer:"); items[i] = int.Parse(Console.ReadLine()); } var flag = Sort(items, (first, second) => { return first > second; }); if (flag) Console.WriteLine("First Parameter is bigger"); else Console.WriteLine("Second Parameter is bigger"); Console.Read(); } static bool Sort(int[] items, Func<int,int,bool> method) { return method(items[0], items[1]); } }
上面一段代碼很簡單,比較兩次輸入的大小,其中使用了lambda表達式來傳遞了比較的方法,那麼通過編譯器編譯以後呢,下面一段代碼展現了編譯器生產的CIL代碼對應的C#代碼:閉包
class Program { static void Main(string[] args) { int[] items = new int[2]; for (int i = 0; i < items.Length; i++) { Console.WriteLine("Enter a integer:"); items[i] = int.Parse(Console.ReadLine()); } var flag = Sort(items,Program.__AnonymousMethod_00000000); if (flag) Console.WriteLine("First Parameter is bigger"); else Console.WriteLine("Second Parameter is bigger"); Console.Read(); } static bool Sort(int[] items, Func<int,int,bool> method) { return method(items[0], items[1]); } private static bool Program.__AnonymousMethod_00000000( int first, int second) { return first < second; } }
一目瞭然,編譯器幫咱們生成了一個static的函數。可能有人要問,跟閉包有什麼關係呢?咱們再看一段代碼:函數
class Program { static void Main(string[] args) { int comparionCount = 0; int[] items = new int[2]; for (int i = 0; i < items.Length; i++) { Console.WriteLine("Enter a integer:"); items[i] = int.Parse(Console.ReadLine()); } var flag = Sort(items, (first, second) => { comparionCount++; return first > second; }); if (flag) Console.WriteLine("First Parameter is bigger"); else Console.WriteLine("Second Parameter is bigger"); Console.WriteLine(string.Format("Items were compared {0} times", comparionCount)); Console.Read(); } static bool Sort(int[] items, Func<int,int,bool> method) { return method(items[0], items[1]); } }
上面這一段代碼閉包就出現了,函數內部讀取了外部函數定義的變量。那編譯器究竟幹了什麼呢,咱們看下面的代碼:spa
class Program { private sealed class class __LocalsDisplayClass_00000001 { public int comparionCount; public bool __AnonymousMethd_00000000(int first,int second) { comparionCount ++; return first>second; } } static void Main(string[] args) { __LocalsDisplayClass_00000001 locals = new __LocalsDisplayClass_00000001 (); locals .comparionCount =0; int[] items = new int[2]; for (int i = 0; i < items.Length; i++) { Console.WriteLine("Enter a integer:"); items[i] = int.Parse(Console.ReadLine()); } var flag = Sort(items,locals.__AnonymousMethd_00000000); if (flag) Console.WriteLine("First Parameter is bigger"); else Console.WriteLine("Second Parameter is bigger"); Console.WriteLine(string.Format("Items were compared {0} times", comparionCount)); Console.Read(); } static bool Sort(int[] items, Func<int,int,bool> method) { return method(items[0], items[1]); } }
被使用的局部變量被看成一個實例字段,包含在編譯器生成的內部類中。code
原文是這麼說的:生成的__LocalsDisplayClass類成爲閉包,它是一個數據結構(一個C#類),其中包含一個表達式以及對錶達式進行求值所需的變量。orm