为什么是&;displayclass &;在堆栈跟踪中按此顺序调用方法名

本文关键字:顺序调用 方法 堆栈 displayclass 为什么 跟踪 | 更新日期: 2023-09-27 18:12:41

首先,我读了这个答案,没有,它只说它现在是如何实现的,但没有解释为什么。

下面是一个示例程序(与这里相同):

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()

注意这两行:

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

下一条(带invoke())表示存在一个命名空间ConsoleApplication1,其中包含Program类,并且有成员invoke()。这里从左到右对应于从外到内。

上面的(c__DisplayClass2)再次表示有一个命名空间和一个类…

然后是c__DisplayClass2,意思是"编译器为存储捕获的变量而选择的神奇名称",然后是<implMain>,好像它是c__DisplayClass2的参数。所以它读起来好像c__DisplayClass2Program的一部分,implMainc__DisplayClass2的一部分。

现在,正如我所看到的,它在逻辑上是相反的-有implMain()方法和专门为implMain()局部变量精心制作的"魔法类"c__DisplayClass2。所以对我来说,上面的行应该是这样的:

at ConsoleApplication1.Program.implMain.c__DisplayClass2.b__0()

(也许用一些额外的符号来防止可能的冲突),但我希望我的想法是明确的-这样看起来c__DisplayClass2是专门为促进implMain()的功能而精心制作的。

当前实现在局部变量捕获类名(c__DisplayClass2)之后显示方法名(implMain)而不是相反,是否有任何原因?

为什么是&;displayclass &;在堆栈跟踪中按此顺序调用方法名

<implMain>b__0()只是方法的名称。

检查反汇编程序会告诉你这一点。<>不表示泛型。

包含implMain可能只是暗示了委托是在哪里创建的