簡體   English   中英

這個編譯器生成的枚舉器是什么意思?

[英]What does this compiler-generated enumerator mean?

我寫了一個相當復雜的方法,yield-returns 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();
}

我猜測(或希望)Reflector錯放了外部switch的右括號,並且它應該在return后直接放置。 不過,我不明白為什么在案例3中有一個空開關,或者為什么在finally塊中調用m__Finallya (正常運行和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/'<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

你沒有展示你的原始迭代器塊是什么樣的,但我對Reflector和編譯器生成的代碼的經驗是它並不總是能夠完全准確地反編譯,因為編譯器使用了一些沒有等效的IL。 C#。

我有一篇關於迭代器塊實現文章可能對你有所幫助,但我不會太擔心編譯代碼的樣子。 在某些情況下,C#編譯器幾乎肯定會生成不必要的代碼,因為這樣可以使編譯器更簡單。 迭代器塊必須非常難以正確(它可能變得非常復雜,最后是塊和迭代器處理)所以我認為僅僅信任JIT來優化掉生成的代碼中的開關/大小寫等不必要的位是合理的。

這只是反射器努力跟上已生成的IL(因為迭代器塊不必與“正常”C#相關,只要它們是有效的IL)。 特別是, retfinally塊之后。

我可以說C#編譯器是愚蠢的,(它可能有點愚蠢)。 當運行時進行jitted時,這個代碼看起來很可能非常不同(所有討厭的垃圾都被省略)。

無論如何,你可能熟悉狀態機嗎? 當您使用C#(yield stuff)編寫生成器時,您告訴編譯器發出一個匿名類型,該類型將此生成器實現為狀態機。 這是一個很好的正式方法,可以驗證。 這可能是它看起來如此的原因。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM