代码之家  ›  专栏  ›  技术社区  ›  Hosam Aly

这个编译器生成的枚举数是什么意思?

  •  4
  • Hosam Aly  · 技术社区  · 16 年前

    我编写了一个相当复杂的方法,可以产生回报 IEnumerable<string> ,但当我在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();
    }
    

    我猜(或希望)是反射器错放了外壳的闭合支架 switch return . 不过,我不明白为什么在案例3中有一个空开关,或者为什么 m__Finallya finally 块(正常运行和内部运行之间是否存在语义差异 最后 块除CER之外,我的代码中没有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/'<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
    
    3 回复  |  直到 13 年前
        1
  •  5
  •   Jon Skeet    16 年前

    我有一个 article about iterator block implementation 这可能会对您有所帮助,但我不会太担心编译后的代码是什么样子的。在某些情况下,C#编译器几乎肯定会生成不必要的代码,因为这样可以使编译器更简单。迭代器块必须非常复杂才能得到正确的结果(它可能会变得非常复杂,有finally块和迭代器处理),所以我认为相信JIT可以优化掉不必要的位,比如生成代码中的switch/case。

        2
  •  4
  •   Marc Gravell    16 年前

    ret 是在 finally

        3
  •  1
  •   John Leidegren    16 年前

    不管怎样,你可能熟悉状态机?当您用C#(yield stuff)编写生成器时,您告诉编译器发出一个匿名类型,该类型将该生成器实现为一个状态机。这是一种很好的形式化方法,可以验证。这可能就是它看起来如此的原因。