根据this answer,当代码使用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
,它是编译器为保存循环变量而生成的类的名称。
根据this answer c__DisplayClass
“表示”
c - &gt;匿名方法闭包类(“DisplayClass”)
好的,但“DisplayClass”在这里意味着什么?
这会产生什么类“显示”?换句话说,为什么它不是“MagicClass”或“GeneratedClass”或任何其他名称?
答案 0 :(得分:33)
来自an answer to a related question by Eric Lippert:
闭包类被称为“DisplayClass”的原因有点不幸:这是调试器团队用来描述在调试器中显示时具有特殊行为的类的行话。显然,当您调试代码时,我们不希望将“x”显示为不可能命名的类的字段;相反,你希望它看起来像任何其他局部变量。调试器中有特殊的装置可以处理这种显示类。它可能应该被称为“ClosureClass”,以便更容易阅读反汇编。
答案 1 :(得分:8)
您可以从SSCLI20发行版csharp / sccomp子目录中获得C#编译器源的一些见解。搜索代码“display”会在fncbind.cpp源代码文件中提供大多数命中。您会看到它在代码符号和注释中使用。
评论强烈建议这是团队内部使用的术语,可能早在设计会议上。这是.NET 2.0复古代码,还没有很多代码重写。只是迭代器和匿名方法,都以非常类似的方式实现。术语“显示类”在注释中偏离“用户类”,这清楚地暗示他们使用该术语来表示自动生成的类。没有强烈暗示为什么“显示”受到青睐,我怀疑它可能与这些类在程序集的元数据中可见有关。
答案 2 :(得分:7)
基于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;
}
}