为什么“DisplayClass”和调用方法名称在堆栈跟踪中以这种方式排序?

时间:2013-05-08 10:08:53

标签: c# .net lambda

首先,我读过this answer而不是,它只是说现在如何实现,但没有解释原因。

这是一个示例程序(与here相同):

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的{​​{1}}个名称空间Program。这里从左到右对应于从外到内。

上面的那个(invoke())再说一个命名空间和一个类......

然后有c__DisplayClass2这意味着“编译器选择用于存储捕获变量的魔术名称”,然后c__DisplayClass2就好像它是<implMain>的参数一样。因此,它看起来好像c__DisplayClass2c__DisplayClass2的一部分,而ProgramimplMain的一部分。

现在我认为它在逻辑上恰恰相反 - 有c__DisplayClass2方法,并且专门为implMain()局部变量设计了“魔术类”c__DisplayClass2。所以对我来说,上面的行看起来应该是这样的:

implMain()

(可能还有一些额外的符号可以防止可能的冲突)但我希望我的想法很明确 - 这样看起来at ConsoleApplication1.Program.implMain.c__DisplayClass2.b__0() 专门用来促进c__DisplayClass2运作。

在局部变量捕获类名(implMain())之后,当前实现是否显示方法名称(implMain)是否有任何理由,反之亦然?

1 个答案:

答案 0 :(得分:3)

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

反汇编程序中的检查将向您显示此信息。 <>并不代表泛型。

包含implMain可能只是提示代表的创建位置。