標籤:
先來一段代碼引入主題。如果你可以直接說出代碼的輸出結果,說明本文不適合你。(代碼引自《深入理解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)
答案
C#:在匿名方法中捕獲外部變數