显示闭包的编译器生成代码

3

我创建了一个小的测试类:

public delegate int Adder();

class Example {
    static Adder CreateAdder() {
        int x = 0;
        return delegate {
            x++;
            return x;
        };
    }

    public static void Test() {
        Adder add = CreateAdder();
        Console.WriteLine(add());
        Console.WriteLine(add());
        Console.WriteLine(add());
    }
}

x是一个闭包变量。现在,我可以用反射器查看编译器生成的以下辅助类:

[CompilerGenerated]
private sealed class <>c__DisplayClass0_0 {
   public int x;
   internal int <CreateAdder>b__0() {
       int x = this.x;
       this.x = x + 1;
       return this.x;
   }
}

但我看不出来这个辅助类将如何在测试方法中使用。有没有可能展示一下使用辅助类的测试方法呢?


1
你可以使用 ILDASM 或 JetBrain 的 dotPeek 工具反编译程序集,查看 Test() 中正在发生什么。 - René Vogt
1个回答

0
事实上,最令人兴奋的部分并不在于Test()。因为Test()只是调用了一个委托(add)。
// decompiled code is the same as original source
public static void Test()
{
  Adder add = Example.CreateAdder();
  Console.WriteLine(add());
  Console.WriteLine(add());
  Console.WriteLine(add());
}

编译器生成的类在CreateAdder()中使用:

private static Adder CreateAdder()
{
  Example.<>c__DisplayClass0_0 cDisplayClass00 = new Example.<>c__DisplayClass0_0();
  cDisplayClass00.x = 0;
  return new Adder((object) cDisplayClass00, __methodptr(<CreateAdder>b__0));
}

因此,要创建委托,需要实例化编译器生成的类的对象。委托将目标指向该对象及其<CreateAdder>b__0方法(该方法表示您在匿名方法中执行的操作)。


我使用了JetBrain's dotPeek来反编译它。ILDASM是微软的另一种选择。


1
谢谢。还有一个问题:你在dotPeek中看到编译器生成的类了吗?我没有 :-( - BennoDual
在工具栏上点击 "Turn Compiler-generated Code On/Off" 按钮,即可显示/隐藏主题图标中的编译器生成代码屏幕。 - Peter

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接