被用在匿名方法中的局部變量有著超出用到它們的外部常規方法的生命周期。這個技術,在其它語言中,就是大家都知道的closures。除去匿名方法提供的簡單語法,closures是匿名方法提供給開發者的一個功能強大的技術。該技術允許委托處理器代碼(匿名方法)訪問在常規方法內部被定義的局部變量。這就允許out-of-band數據,除了委托參數之外還有數據將被傳遞到委托,以供在其方法執行時使用。沒有這個技術,每個委托和其相應的處理器方法就不得不聲明表示局部上下文數據的參數,隨著時間的過去這(譯注:指不斷聲明表示局部上下文數據的參數)將變得難於管理。 匿名方法的作用域和局部變量用法
我們討論了在方法的主作用域(the main scope)中的匿名方法的實現。當一個匿名方法在一個嵌套作用域中被定義時,並且匿名方法中用到獨立作用域級的局部變量,C#為每個作用域創建一個private內部類。比如,假設scope 1有局部變量iTemp,而scope 2,是scope 1的嵌套作用域,有一個局部變量jTemp。讓在使用來自scope 1 和 scope 2局部變量iTemp 和 jTemp的 scope 2中,我們定義一個匿名方法。下面的代碼顯示了上面描述的示例:
public class Program
{
public delegate void MyDelegate();
public static void Main(string[] args)
{
MyDelegate dlg = null;
int iTemp = 100;
if (iTemp > 50)
{
int jTemp = 200;
dlg = delegate
{
Console.WriteLine("iTemp: {0}, jTemp: {1}",iTemp,jTemp);
};
}
dlg();
}
}
當上面的代碼被編譯時,C#編譯器在''Program''類中創建兩個內部類。一個內部類包裝局部變量iTemp作為一個public數據成員。第二個內部類包裝在嵌套作用域中的局部變量,jTemp,作為一個public數據成員,同時在相同的嵌套作用域中包裝匿名方法作為public實例方法。C#編譯器為上面的代碼生成下面的偽代碼:
public class Program
{
//包裝來自外部作用域的局部變量''iTemp''的類
private class InnerClassScope1
{
public int iTemp;
}
//包裝來自內部作用域和匿名方法的局部變量的類
private class InnerClassScope2
{
public void InstanceMethod()
{
Console.WriteLine("iTemp: {0}, jTemp: {1}", localObjectScope1.iTemp, jTemp);
}
public InnerClassScope1 localObjectScope1;
public int jTemp;
}
public delegate void MyDelegate();
public static void Main(string[] args)
{
MyDelegate dlg = null;
InnerClassScope1 localObject1 = new InnerClassScope1();
localObject1.iTemp = 100;
if (localObject1.iTemp > 50)
{
InnerClassScope2 localObject2 = new InnerClassScope2();
localObject2.localObjectScope1 = localObject1;
localObject2.jTemp = 200;
dlg = new MyDelegate(localObject2.InstanceMethod);
}
dlg();
}
}
正如上面的代碼所示,包裝匿名方法的內部類將擁有所有代表外部作用域局部變量的對象,這些變量被用在匿名方法中,像public數據成員。下圖顯示了C#默默創建的內部類的ILDASM視圖: