根据这个答案,当代码使用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();
}
}
Run Code Online (Sandbox Code Playgroud)
输出以下调用堆栈:
System.InvalidOperationException
at ConsoleApplication1.Program.<>c__DisplayClass2.<implMain>b__0()
at ConsoleApplication1.Program.invoke(Action what)
at ConsoleApplication1.Program.implMain()
at ConsoleApplication1.Program.Main()
Run Code Online (Sandbox Code Playgroud)
请注意,c__DisplayClass2其中有一个由编译器生成的用于保存循环变量的类的名称.
根据这个答案 c__DisplayClass "手段"
c - >匿名方法闭包类("DisplayClass")
好的,但"DisplayClass"在这里意味着什么?
这会产生什么类"显示"?换句话说,为什么它不是"MagicClass"或"GeneratedClass"或任何其他名称?
svi*_*ick 34
闭包类被称为"DisplayClass"的原因有点不幸:这是调试器团队用来描述在调试器中显示时具有特殊行为的类的行话.显然,当您调试代码时,我们不希望将"x"显示为不可能命名的类的字段; 相反,你希望它看起来像任何其他局部变量.调试器中有特殊的装置可以处理这种显示类.它可能应该被称为"ClosureClass",以便更容易阅读反汇编.
您可以从SSCLI20发行版csharp/sccomp子目录中获得C#编译器源的一些见解.搜索代码"display"会在fncbind.cpp源代码文件中提供大多数命中.你会看到它在代码符号和注释中使用.
评论强烈建议这是团队内部使用的术语,可能早在设计会议上.这是.NET 2.0复古代码,还没有很多代码重写.只是迭代器和匿名方法,都以非常类似的方式实现.术语"显示类"在注释中偏离"用户类",这清楚地暗示他们使用该术语来表示自动生成的类.没有强烈暗示为什么"显示"受到青睐,我怀疑它可能与这些类在程序集的元数据中可见有关.
小智 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;
}
}
Run Code Online (Sandbox Code Playgroud)