在這個例子中,匿名方法捕獲了一個局部變量。
class Test
{
void F() {
int y = 123;
D d = delegate { Console.WriteLine(y); };
}
}
該局部變量的生存期現在至少必須延長到匿名方法委托的生存期為止。這可以通過將局部變量“提升(lifting)”為編譯器生成的(compiler-generated)類的字段來完成。局部變量的實例化對應於創建一個編譯器生成的類的實例,而訪問局部變量將對應於訪問編譯器生成的類實例的一個字段。並且,匿名方法將成為編譯器生成類的實例方法。
class Test
{
void F() {
__locals1 = new __Locals1();
__locals1.y = 123;
D d = new D(__locals1.__Method1);
}
class __Locals1
{
public int y;
public void __Method1() {
Console.WriteLine(y);
}
}
}
最後,如下匿名方法將捕獲this,以及具有不同生存期的兩個局部變量。
class Test
{
int x;
void F() {
int y = 123;
for (int i = 0; i < 10; i++) {
int z = i * 2;
D d = delegate { Console.WriteLine(x + y + z); };
}
}
}
在這裡,編譯器將為每個語句塊生成類,在這些語句塊中局部變量將被捕獲,而在不同塊中的局部變量將會有獨立的生存期。
__Locals2的實例,編譯器為內部語句塊生成的類,包含局部變量z和引用__Locals1實例的字段。__Locals1的實例,編譯器為外部語句塊生成的類,包含局部變量y和引用封閉函數成員的this的字段。通過這些數據結構,你可以通過__Locals2的一個實例到達所有被捕獲的局部變量,並且匿名方法的代碼可以作為那個類的實例方法而實現。
class Test
{
void F() {
__locals1 = new __Locals1();
__locals1.__this = this;
__locals1.y = 123;
for (int i = 0; i < 10; i++) {
__locals2 = new __Locals2();
__locals2.__locals1 = __locals1;
__locals2.z = i * 2;
D d = new D(__locals2.__Method1);
}
}
class __Locals1
{
public Test __this;
public int y;
}
class __Locals2
{
public __Locals1 __locals1;
public int z;
public void __Method1() {
Console.WriteLine(__locals1.__this.x + __locals1.y + z);
}
}
}