先來一段代碼引入主題。如果你可以直接說出代碼的輸出結果,說明本文不適合你。(代碼引自《深入理解C#》第三版)
class Program { private delegate void TestDelegate(); static void Main(string[] args) { TestDelegate[] delegates = new TestDelegate[2]; int outside = 0; for(int i = 0; i < 2; i++) { int inside = 0; delegates[i] = delegate { Console.WriteLine("({0},{1})", outside, inside); outside++; inside++; }; } delegates[0](); delegates[0](); delegates[0](); delegates[1](); delegates[1](); Console.ReadKey(); } }
答案在本文最下方。
先引入兩個定義:
1、外部變量:是指作用域內包括匿名方法的局部變量或參數。
2、捕獲的外部變量:是指在匿名方法中使用的外部變量。
定義有點抽象,針對上面的代碼而言,inside和outside都是匿名方法的外部變量,而inside和outside同樣也作為被匿名方法捕獲的外部變量,因為在匿名方法體中引用了這兩個變量。
而被匿名方法捕獲到的是變量本身,而並非變量的值。針對上面的代碼而言,執行outside++和inside++時,操作的其實就是外部的inside和outside變量。
至此,我們應該可以得出outside的變化應該是從0到4。
那麼程序的輸出也應該是這個樣子的:(X代碼未知)
(0,X)
(1,X)
(2,X)
(3,X)
(4,X)
實際上,在for循環體裡面做的東西就是實例化了兩個TestDelegate委托對象:delegate[0]和delegate[1]
而循環的執行,實際上會實例化兩個名稱都為inside的變量。
這兩個變量之間沒有什麼關聯,僅僅是名稱一樣而已。
這兩個變量分別作為delegate[0]和delegate[1]的外部捕獲變量。也就是delegate[0]和delegate[1]在操作inside時,是互不影響的。
於是,得出答案:
(0,0) (1,1) (2,2) (3,0) (4,1) 答案