【问题标题】:Correct understanding of a .NET stack trace with delegates正确理解带有委托的 .NET 堆栈跟踪
【发布时间】:2021-08-30 05:49:51
【问题描述】:

我正在尝试更深入地了解 .NET 堆栈跟踪中的每一帧。大多数堆栈跟踪都很容易理解。我也知道像 Ben.Demystifier 这样的包,使其更具可读性。这是我试图更好地理解的堆栈帧示例:

Microsoft.AspNetCore.Mvc.Controllers.ControllerBinderDelegateProvider.<>c__DisplayClass0_0.<<CreateBinderDelegate>g__Bind|0>d.MoveNext()

据我了解,Microsoft.AspNetCore.Mvc.Controllers 部分是命名空间,ControllerBinderDelegateProvider 是一个类,MoveNext() 是一个方法。 &lt;&gt;c__DisplayClass0_0.&lt;&lt;CreateBinderDelegate&gt;g__Bind|0&gt;d 部分怎么样?有人可以帮忙解释一下这个封面吗?

【问题讨论】:

标签: c# .net


【解决方案1】:

&lt;&gt;c__DisplayClass0_0.&lt;&lt;CreateBinderDelegate&gt;g__Bind|0&gt;d 部分由 C# 编译器生成。在引用的情况下,它是专门为 the local function Bind 在方法 CreateBinderDelegate 中生成的,该方法属于 ControllerBinderDelegateProvider 类,位于命名空间 Microsoft.AspNetCore.Mvc.Controllers 下。

要了解名称的各个部分,请遵循编译器/Roslyn 源代码中的GeneratedNames.MakeLocalFunctionName。它调用了主力方法MakeMethodScopedSynthesizedName

实现细节可能会随着时间而改变,但现在,这里是&lt;&gt;c__DisplayClass0_0.&lt;&lt;CreateBinderDelegate&gt;g__Bind|0&gt;d 的粗略细分,您可以看到它由几个部分组成:

  1. &lt;&gt;c__DisplayClass0_0
  2. &lt;CreateBinderDelegate&gt;g__Bind|0
  3. &lt;...&gt;d&lt;&lt;CreateBinderDelegate&gt;g__Bind|0&gt;d

注意,在第三种情况下,第二种是嵌入的。

MakeMethodScopedSynthesizedName 创建的所有合成名称基于参数名称具有以下模式:

"<" methodName? ">" kind
  ( "__" suffix suffixTerminator? )?
  ( methodOrdinal ("#" methodGeneration )?
  | entityOrdinal ("#" entityGeneration )?
  | methodOrdinal ("#" methodGeneration )?
    "_"
    entityOrdinal ("#" entityGeneration )?
  )?

在上述模式中,引号("...")中的任何内容都是文字,括号((...))用于分组,? 表示可选,| 表示methodNamesuffix 等标识符表示 MakeMethodScopedSynthesizedName 参数的值。

&lt;&gt;c__DisplayClass0_0 部分是通过调用GeneratedNames.MakeLambdaDisplayClassName 生成的:

MakeMethodScopedSynthesizedName(GeneratedNameKind.LambdaDisplayClass,
                                methodOrdinal, generation,
                                suffix: "DisplayClass",
                                entityOrdinal: closureOrdinal,
                                entityGeneration: closureGeneration);

由于methodName为空,合成名称以&lt;&gt;开头,c来自GeneratedNameKind.LambdaDisplayClass,后缀显然是DisplayClass0_0来自假设methodOrdinal和@ 987654359@ 在该呼叫中为零。

您可以按照来源查看其他部分是如何使用MakeMethodScopedSynthesizedName 的变体构建的,但简而言之:

  • &lt;CreateBinderDelegate&gt;g__Bind|0 部分是通过调用GeneratedNames.MakeLocalFunctionName 生成的。
    MakeMethodScopedSynthesizedName(GeneratedNameKind.LocalFunction, methodOrdinal, methodGeneration, methodName, localFunctionName, GeneratedNameConstants.LocalFunctionNameTerminator, lambdaOrdinal, lambdaGeneration);
    
  • &lt;...&gt;d 部分由GeneratedNames.MakeStateMachineTypeName 生成,其中... 来自methodName 值:
    MakeMethodScopedSynthesizedName(GeneratedNameKind.StateMachineType, methodOrdinal, generation, methodName);
    

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-02-19
    • 1970-01-01
    • 2010-09-20
    • 1970-01-01
    • 2018-06-24
    • 2020-10-19
    • 1970-01-01
    相关资源
    最近更新 更多