c# - 正确理解带有委托的 .NET 堆栈跟踪
问题描述
我试图更深入地了解 .NET 堆栈跟踪中的每一帧。大多数堆栈跟踪都很容易理解。我也知道像 Ben.Demystifier 这样的包,使其更具可读性。这是我试图更好地理解的堆栈框架的示例:
Microsoft.AspNetCore.Mvc.Controllers.ControllerBinderDelegateProvider.<>c__DisplayClass0_0.<<CreateBinderDelegate>g__Bind|0>d.MoveNext()
据我了解,这Microsoft.AspNetCore.Mvc.Controllers
部分是命名空间,ControllerBinderDelegateProvider
是一个类,MoveNext()
是一个方法。<>c__DisplayClass0_0.<<CreateBinderDelegate>g__Bind|0>d
有人可以帮助解释这部分内容吗?
解决方案
该<>c__DisplayClass0_0.<<CreateBinderDelegate>g__Bind|0>d
部分由 C# 编译器生成。在引用的情况下,它是专门为属于该类的方法中的本地函数Bind
生成的,该方法位于命名空间下。CreateBinderDelegate
ControllerBinderDelegateProvider
Microsoft.AspNetCore.Mvc.Controllers
要了解名称的各个部分,请遵循GeneratedNames.MakeLocalFunctionName
编译器/Roslyn 源代码。它调用主要的主力方法MakeMethodScopedSynthesizedName
。
实现细节可能会随着时间而改变,但现在,这里是一个粗略的细分<>c__DisplayClass0_0.<<CreateBinderDelegate>g__Bind|0>d
,您可以看到它由几个部分组成:
<>c__DisplayClass0_0
<CreateBinderDelegate>g__Bind|0
<...>d
或者<<CreateBinderDelegate>g__Bind|0>d
请注意,在第三种情况下,第二个是嵌入的。
由 所创建的所有合成名称MakeMethodScopedSynthesizedName
都具有以下基于参数名称的模式:
"<" methodName? ">" kind
( "__" suffix suffixTerminator? )?
( methodOrdinal ("#" methodGeneration )?
| entityOrdinal ("#" entityGeneration )?
| methodOrdinal ("#" methodGeneration )?
"_"
entityOrdinal ("#" entityGeneration )?
)?
在上述模式中,引号 ( "..."
) 中的任何内容都是文字,括号 ( (...)
) 用于分组,?
表示可选,|
表示ormethodName
,以及类似和的标识符suffix
表示MakeMethodScopedSynthesizedName
参数的值。
该<>c__DisplayClass0_0
部分是通过调用生成的GeneratedNames.MakeLambdaDisplayClassName
:
MakeMethodScopedSynthesizedName(GeneratedNameKind.LambdaDisplayClass,
methodOrdinal, generation,
suffix: "DisplayClass",
entityOrdinal: closureOrdinal,
entityGeneration: closureGeneration);
由于methodName
为 null,因此合成名称以 开头<>
,c
来自GeneratedNameKind.LambdaDisplayClass
,后缀显然DisplayClass
是0_0
来自,并且假设该调用为methodOrdinal
andgeneration
为零。
您可以按照来源查看其他部分是如何使用 的变体构建的MakeMethodScopedSynthesizedName
,但简而言之:
- 该
<CreateBinderDelegate>g__Bind|0
部分是通过调用生成的GeneratedNames.MakeLocalFunctionName
。MakeMethodScopedSynthesizedName(GeneratedNameKind.LocalFunction, methodOrdinal, methodGeneration, methodName, localFunctionName, GeneratedNameConstants.LocalFunctionNameTerminator, lambdaOrdinal, lambdaGeneration);
- 该
<...>d
部分由值GeneratedNames.MakeStateMachineTypeName
的...
来源生成methodName
:MakeMethodScopedSynthesizedName(GeneratedNameKind.StateMachineType, methodOrdinal, generation, methodName);