首先,我已经阅读了这个答案,不,它只说明了它现在是如何实现的,但没有解释为什么。
这是一个示例程序(与此处相同):
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)
较低的 (with invoke()
) 表示其中有ConsoleApplication1
带有类的名称空间Program
,其中有 member invoke()
。这里从左到右对应于从外到内。
上面的(带c__DisplayClass2
)再次表示有一个命名空间和一个类......
然后c__DisplayClass2
是“编译器选择用于存储捕获的变量的神奇名称”,然后就<implMain>
好像它是c__DisplayClass2
. 所以它读起来好像不知何故c__DisplayClass2
是.Program
implMain
c__DisplayClass2
现在我看到它在逻辑上是相反的——有方法,有专门为局部变量设计implMain()
的“魔术类” 。所以对我来说,上面的行看起来应该是这样的:c__DisplayClass2
implMain()
at ConsoleApplication1.Program.implMain.c__DisplayClass2.b__0()
(也许有一些额外的符号来防止可能的冲突)但我希望我的想法很清楚——这样它看起来就像c__DisplayClass2
是专门为促进implMain()
功能而设计的。
implMain
当前实现在局部变量捕获类名()之后显示方法名( c__DisplayClass2
)而不是反之亦然,是否有任何理由?