![](/img/trans.png)
[英]Why are “DisplayClass” and calling method name ordered this way in the stack trace?
[英]What does "DisplayClass" name mean when calling lambda?
根据这个答案,当代码使用来自 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”在这里是什么意思?
这个生成的类“显示”什么? 换句话说,为什么它不是“MagicClass”或“GeneratedClass”或任何其他名称?
闭包类被称为“DisplayClass”的原因有点不幸:这是调试器团队用来描述在调试器中显示时具有特殊行为的类的行话。 显然,我们不希望在调试代码时将“x”显示为一个不可能命名的类的字段; 相反,您希望它看起来像任何其他局部变量。 调试器中有特殊的装置来处理这种显示类。 它可能应该被称为“ClosureClass”,以便更容易阅读反汇编。
您可以从 SSCLI20 发行版 csharp/sccomp 子目录中的 C# 编译器源中获得一些见解。 在 fncbind.cpp 源代码文件中搜索“display”的代码会得到最多的点击。 您会看到它在代码符号和注释中使用。
评论强烈暗示这是团队内部使用的一个术语,可能早在设计会议上。 这是 .NET 2.0 老式代码,尚未进行大量代码重写。 只是迭代器和匿名方法,两者都以非常相似的方式实现。 术语“显示类”与注释中的“用户类”有所偏移,清楚地暗示他们使用该术语来表示自动生成的类。 没有强烈暗示为什么“显示”受到青睐,我怀疑这可能与这些类在程序集的元数据中可见有关。
基于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;
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.