调用lambda时,“DisplayClass”名称代表什么意思?

59

根据这个答案,当代码在lambda方法中使用局部变量时,编译器会生成额外的类,这些类可能有类似于c__DisplayClass1的名称。例如,以下(完全无用的)代码:

class Program
{
    static void Main()
    {
        try {
            implMain();
        } catch (Exception e) {
            Console.WriteLine(e.ToString());
        }
    }

    static void implMain()
    {
        for (int i = 0; i < 10; i++) {
            invoke(() => {
                Console.WriteLine(i);
                throw new InvalidOperationException();
            });
        }
    }
    static void invoke(Action what)
    {
        what();
    }
}

输出以下调用堆栈:

System.InvalidOperationException
at ConsoleApplication1.Program.<>c__DisplayClass2.<implMain>b__0()
at ConsoleApplication1.Program.invoke(Action what)
at ConsoleApplication1.Program.implMain()
at ConsoleApplication1.Program.Main()

请注意,其中有一个名为 c__DisplayClass2 的类,它是编译器生成的用于保存循环变量的类的名称。

根据这个答案c__DisplayClass 表示:

c --> 匿名方法闭包类 ("DisplayClass")

好的,但这里的 "DisplayClass" 是什么意思?

这个生成的类 "display" 了什么?换句话说,为什么它不叫做 "MagicClass" 或 "GeneratedClass" 或任何其他名称?

3个回答

55

来自Eric Lippert回答相关问题的答案

闭包类被称为“DisplayClass”的原因有点不幸:这是调试器团队用来描述在调试器中显示类时具有特殊行为的术语。显然,当您调试代码时,我们不希望将“x”显示为一个名称难以想象的类的字段;相反,您希望它看起来像任何其他本地变量。调试器中有特殊的工具来处理此类显示类。它可能应该被称为“ClosureClass”,以使阅读反汇编更容易。


16
您可以从SSCLI20分发中的csharp/sccomp子目录获取C#编译器源代码,从"fncbind.cpp"源代码文件中搜索"display"关键字可得到大多数搜索结果。您将看到它在代码符号以及注释中的使用。
注释强烈暗示这是团队内部使用的术语,可能追溯到设计会议时期。这是.NET 2.0的代码,尚未进行太多的代码重写。只有迭代器和匿名方法,两者都采用非常相似的实现方式。 "Display class"一词在注释中与"user class"分开,明显提示他们使用该术语来表示自动生成的类。没有强烈的暗示为什么会选择“display”,我怀疑这可能与这些类在程序集元数据中可见有关。

10

基于Reflector,DisplayClass可以翻译为CompilerGeneratedClass。

[CompilerGenerated]
private sealed class <>c__DisplayClass16b
{
// Fields
public MainForm <>4__this;
public object sender;

// Methods
public void <cmdADSInit_Click>b__16a()
  {
    ADS.Initialize();
    this.<>4__this._Sender = this.sender;
    this.<>4__this.SelectedObject = ADS.Instance;
  }
}

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