gpt4 book ai didi

c# - 为什么代码生成名为 <>c__DisplayClass1 的 MSIL 类

转载 作者:太空狗 更新时间:2023-10-29 19:58:52 26 4
gpt4 key购买 nike

我有这个代码,

private bool MatchingBreak(IEnumerable<CarriagewaySummary> breaks, int startMetres, int divisionPosition)
{
CarriagewaySummary matchingBreak = breaks.Where(x =>
{
return x.StartMetres == startMetres && x.EndMetres == divisionPosition;
}).SingleOrDefault();
return matchingBreak != null;
}

为什么会在 MSIL 中生成一个名为 <>c__DisplayClass1 的嵌套类?

.class nested private auto ansi sealed beforefieldinit <>c__DisplayClass1
extends object
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilerGeneratedAttribute::.ctor() = (
01 00 00 00
)
// Fields
.field public int32 startMetres
.field public int32 divisionPosition

// Methods
.method public hidebysig specialname rtspecialname
instance void .ctor () cil managed
{
// Method begins at RVA 0x56fb
// Code size 7 (0x7)
.maxstack 8

IL_0000: ldarg.0
IL_0001: call instance void object::.ctor()
IL_0006: ret
} // End of method <>c__DisplayClass1..ctor

.method public hidebysig
instance bool <MatchingBreak>b__0 (
class TreatmentLengthDynamicSegmentation.Domain.CarriagewaySummary x
) cil managed
{
// Method begins at RVA 0x5704
// Code size 37 (0x25)
.maxstack 2
.locals init (
[0] bool
)

IL_0000: nop
IL_0001: ldarg.1
IL_0002: callvirt instance int32 TreatmentLengthDynamicSegmentation.Domain.CarriagewaySummary::get_StartMetres()
IL_0007: ldarg.0
IL_0008: ldfld int32 class TreatmentLengthDynamicSegmentation.ScriptHelpers.DivisionManager/<>c__DisplayClass1::startMetres
IL_000d: bne.un.s IL_001f
IL_000f: ldarg.1
IL_0010: callvirt instance int32 TreatmentLengthDynamicSegmentation.Domain.CarriagewaySummary::get_EndMetres()
IL_0015: ldarg.0
IL_0016: ldfld int32 class TreatmentLengthDynamicSegmentation.ScriptHelpers.DivisionManager/<>c__DisplayClass1::divisionPosition
IL_001b: ceq
IL_001d: br.s IL_0020
IL_001f: ldc.i4.0
IL_0020: stloc.0
IL_0021: br.s IL_0023
IL_0023: ldloc.0
IL_0024: ret
} // End of method <>c__DisplayClass1.<MatchingBreak>b__0

} // End of class TreatmentLengthDynamicSegmentation.ScriptHelpers.DivisionManager/<>c__DisplayClass1

生成的代码干扰了 Nitriq 代码分析,所以我想了解它存在的原因。

最佳答案

如果你在 lambda 中使用局部变量,它需要在堆上。 lambda 可能会在创建它的函数退出后使用。正常的局部变量(存在于堆栈/寄存器中)在函数退出时变得无效,因此不能在这里使用。

因此,C# 编译器创建了一个类来保存捕获的局部变量。这就是您看到的那个。

请注意,C# 捕获的是实际变量,而不是其当前值。所以从概念上讲,它是通过引用捕获的。捕获的语义意味着编译器需要为每个作用域创建一个容器对象。

http://csharpindepth.com/Articles/Chapter5/Closures.aspx


在你的代码中

x =>
{
return x.StartMetres == startMetres && x.EndMetres == divisionPosition;
}

lambda 使用 startMetresdivisionPosition,因此它们都被捕获并放入该嵌套类中。

关于c# - 为什么代码生成名为 <>c__DisplayClass1 的 MSIL 类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6013094/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com