调用 lambda 时,“DisplayClass”名称是啥意思?

Posted

技术标签:

【中文标题】调用 lambda 时,“DisplayClass”名称是啥意思?【英文标题】:What does "DisplayClass" name mean when calling lambda?调用 lambda 时,“DisplayClass”名称是什么意思? 【发布时间】:2013-04-30 09:24:54 【问题描述】:

根据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 answerc__DisplayClass“意思”

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

好的,但是“DisplayClass”在这里是什么意思?

这个生成的类“显示”了什么?换句话说,为什么不是“MagicClass”或“GeneratedClass”或任何其他名称?

【问题讨论】:

【参考方案1】:

来自an answer to a related question by Eric Lippert:

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

【讨论】:

【参考方案2】:

您可以从 SSCLI20 发行版 csharp/sccomp 子目录中的 C# 编译器源代码中获得一些见解。在代码中搜索“display”会在 fncbind.cpp 源代码文件中找到最多的结果。您会看到它在代码符号和 cmets 中使用。

cmets 强烈建议这是团队内部使用的一个术语,可能早在设计会议上。这是 .NET 2.0 的老式代码,还没有进行很多代码重写。只是迭代器和匿名方法,两者都以非常相似的方式实现。术语“显示类”与 cmets 中的“用户类”有所不同,这清楚地表明他们使用该术语来表示自动生成的类。没有强烈暗示为什么偏爱“显示”,我怀疑这可能与这些类在程序集的元数据中可见有关。

【讨论】:

【参考方案3】:

基于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;
  

【讨论】:

以上是关于调用 lambda 时,“DisplayClass”名称是啥意思?的主要内容,如果未能解决你的问题,请参考以下文章

如何识别c__DisplayClass未标记为可序列化的位置

使用“事件”调用类型时未调用 AWS Lambda

闲置时,带有 Lambda 的 API 网关在第一次调用时返回 404?

Lambda 异步调用

TypeError: 'int' 对象在使用 reduce 和 lambda 时不可调用

AWS lambda 实例在 xstate 调用承诺时关闭