我写了一个相当复杂的yield-returns方法IEnumerable
,但是当我在Reflector中检查编译器输出时,我并不了解编译器生成的实现的特定部分IEnumerator
:
void IDisposable.Dispose() { switch (this.<>1__state) { case 1: case 2: case 3: switch (this.<>1__state) // empty switch! why?! { } break; default: return; try // What?! AFTER return?! { } finally // is the try-finally block anyhow relevant? { this.<>m__Finallya(); } break; } this.<>m__Finally7(); }
我猜测(或希望)Reflector错位了外部的右支撑switch
,并且它应该直接在后面return
.不过,我不明白为什么在案例3中有一个空开关,或者为什么m__Finallya
在一个finally
块中被调用.(正常运行和finally
块内部之间是否存在语义差异?除了CER之外,我的代码中没有.)
作为参考,这是IL:
.method private hidebysig newslot virtual final instance void System.IDisposable.Dispose() cil managed { .override [mscorlib]System.IDisposable::Dispose // Code size 69 (0x45) .maxstack 2 .locals init ([0] int32 CS$0$0000, [1] int32 CS$0$0001) IL_0000: ldarg.0 IL_0001: ldfld int32 FBD.TIP.Reader.MissingMessagesReader/'d__0'::'<>1__state' IL_0006: stloc.0 IL_0007: ldloc.0 IL_0008: ldc.i4.1 IL_0009: sub IL_000a: switch ( IL_001c, IL_001c, IL_001c) IL_001b: ret IL_001c: ldarg.0 IL_001d: ldfld int32 FBD.TIP.Reader.MissingMessagesReader/' d__0'::'<>1__state' IL_0022: stloc.1 IL_0023: ldloc.1 IL_0024: ldc.i4.2 IL_0025: sub IL_0026: switch ( IL_0035, IL_0035) IL_0033: br.s IL_003e .try { IL_0035: leave.s IL_003e } // end .try finally { IL_0037: ldarg.0 IL_0038: call instance void FBD.TIP.Reader.MissingMessagesReader/' d__0'::'<>m__Finallya'() IL_003d: endfinally } // end handler IL_003e: ldarg.0 IL_003f: call instance void FBD.TIP.Reader.MissingMessagesReader/' d__0'::'<>m__Finally7'() IL_0044: ret } // end of method ' d__0'::System.IDisposable.Dispose
Jon Skeet.. 5
你没有展示你的原始迭代器块是什么样的,但我对Reflector和编译器生成的代码的经验是它并不总是能够完全准确地反编译,因为编译器使用了一些没有等效的IL. C#.
我有一篇关于迭代器块实现的文章可能对你有所帮助,但我不会太担心编译代码的样子.在某些情况下,C#编译器几乎肯定会生成不必要的代码,因为这样可以使编译器更简单.迭代器块必须非常难以正确(它可能变得非常复杂,最后是块和迭代器处理)所以我认为仅仅信任JIT来优化掉生成的代码中的开关/大小写等不必要的位是合理的.
你没有展示你的原始迭代器块是什么样的,但我对Reflector和编译器生成的代码的经验是它并不总是能够完全准确地反编译,因为编译器使用了一些没有等效的IL. C#.
我有一篇关于迭代器块实现的文章可能对你有所帮助,但我不会太担心编译代码的样子.在某些情况下,C#编译器几乎肯定会生成不必要的代码,因为这样可以使编译器更简单.迭代器块必须非常难以正确(它可能变得非常复杂,最后是块和迭代器处理)所以我认为仅仅信任JIT来优化掉生成的代码中的开关/大小写等不必要的位是合理的.