匿名方法的局部變量用法
到現在為止,我們對匿名方法如何工作以及內部如何實現有了一點基本的理解。從根本上說,C#創建了private方法來包裝匿名方法。同時這些方法的簽名與它們被分配到的委托相匹配。現在,讓我們看看下面的代碼:
public class Program
{
public delegate void MyDelegate();
public static void Main(string[] args)
{
int iTemp = 100;
MyDelegate dlg = delegate
{
Console.WriteLine(iTemp);
};
dlg();
}
}
對於我們到現在為止對匿名方法已了解的內容來說,這段代碼不應該編譯。因為我們沒有使用如何實例數據成員,C#編譯器應該在''Program''類中創建一個private靜態方法來包裝這個匿名方法。但是新的方法如何訪問局部變量呢?這讓我們相信該代碼將不能被編譯。但是令人驚訝的是,C#編譯器成功編譯了這個代碼而沒有任何錯誤或報警。而且,當你執行這個示例時,在控制台屏幕上輸出打印出iTemp變量的正確的值。現在讓我們進入匿名方法的高級話題。一個匿名方法有封裝在其方法體中使用了的環境變量的值的能力。這個封裝應用於匿名方法被定義的方法中的所有局部變量。當C#編譯器在一個匿名方法的方法體中識別出用到一個局部變量,它就會做如下事情:
1.創建一個新的private類作為匿名方法被定義的類的一個內部類。
2.在新類(譯注:即內部類)中創建一個公共數據成員,使用與用在匿名方法體中的局部變量相同的類型和名稱。
3.在包裝匿名方法的新類中創建一個public實例方法。
4.用新類中的聲明替代局部變量的聲明。創建該新類的一個實例代替局部變量的聲明。
5.用新類實例的數據成員替代在匿名方法體內部和外部使用的局部變量。
6.用在新類中定義的實例方法的地址取代匿名方法的定義。
因此在編譯時,上面的代碼將被C#編譯器翻譯為如下代碼:
public class Program
{
private class InnerClass
{
private void InstanceMethod()
{
Console.WriteLine(iTemp);
}
public int iTemp;
}
public delegate void MyDelegate();
public static void Main(string[] args)
{
InnerClass localObject = new InnerClass();
localObject.iTemp = 100;
MyDelegate dlg = new MyDelegate(localObject.InstanceMethod);
dlg();
}
}
正如上面的偽代碼所示,C#編譯器為''Program''類生成了一個private內部類。在匿名方法中使用的局部變量作為新的已創建的內部類的一個實例數據成員而捕獲。並且匿名方法本身被包裝在內部類的實例方法中。最後,該實例方法在Main方法中作為一個委托處理器而使用。這樣,當委托被調用時,對於在被封裝入匿名方法中的局部變量將會有一個正確的值。下面圖中選定的部分顯示了由C#編譯器默默添加到''Program'' 類的新的private內部類。