I wrote a fairly complex method that yield-returns IEnumerable<string>, but when I inspected the compiler output in Reflector, I didn’t understand a specific part of the compiler-generated implementation of 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(); }
I’m guessing (or hoping) that Reflector misplaced the closing brace of the outer switch, and that it should be directly after the return. Still, I don’t understand why there is an empty switch in case 3, or why m__Finallya is being called in a finally block. (Is there a semantic difference between running normally and inside a finally block? Other than CER’s, which I don’t have in my code.)
For reference, here is the 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/'<GetMissingMessages>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/'<GetMissingMessages>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/'<GetMissingMessages>d__0'::'<>m__Finallya'() IL_003d: endfinally } // end handler IL_003e: ldarg.0 IL_003f: call instance void FBD.TIP.Reader.MissingMessagesReader/'<GetMissingMessages>d__0'::'<>m__Finally7'() IL_0044: ret } // end of method '<GetMissingMessages>d__0'::System.IDisposable.Dispose
That is simply reflector struggling to keep up with the IL that has been generated (since iterator blocks don’t have to relate to ‘normal’ C# as long as they are valid IL). In particular, the
retis after thefinallyblock.