首页 > 解决方案 > 正确理解带有委托的 .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#.net

解决方案


<>c__DisplayClass0_0.<<CreateBinderDelegate>g__Bind|0>d部分由 C# 编译器生成。在引用的情况下,它是专门为属于该类的方法中的本地函数Bind生成的,该方法位于命名空间下。CreateBinderDelegateControllerBinderDelegateProviderMicrosoft.AspNetCore.Mvc.Controllers

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

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

  1. <>c__DisplayClass0_0
  2. <CreateBinderDelegate>g__Bind|0
  3. <...>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,后缀显然DisplayClass0_0来自,并且假设该调用为methodOrdinalandgeneration为零。

您可以按照来源查看其他部分是如何使用 的变体构建的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);
    

推荐阅读