문제

나는 수익을 얻는 상당히 복잡한 방법을 썼습니다 IEnumerable<string>, 그러나 반사기에서 컴파일러 출력을 검사했을 때 컴파일러 생성 구현의 특정 부분을 이해하지 못했습니다. 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. 그래도 Case 3에 빈 스위치가 왜 있는지 또는 왜 m__Finallya a finally 차단하다. (정상적으로 그리고 내부에서 실행하는 것 사이에 의미 적 차이가 있습니까? finally 차단하다? 내 코드에없는 Cer 's 외에.)

참고로 다음은 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
도움이 되었습니까?

해결책

그것은 단순히 생성 된 IL을 따라 잡기 위해 고군분투하는 단순히 반사기입니다 (반복자 블록은 유효한 IL 인 "정상"C#과 관련이 없기 때문에). 특히, ret 후에 finally 차단하다.

다른 팁

원래 반복자 블록의 모습을 보여주지 않았지만 반사기 및 컴파일러 생성 코드에 대한 내 경험은 컴파일러가 동등한 IL을 사용하기 때문에 항상 정확하게 완전히 분리되지는 않는다는 것입니다. 씨#.

나는있다 반복자 블록 구현에 관한 기사 조금 도움이 될 수 있지만 컴파일 된 코드가 어떻게 보이는지 너무 걱정하지 않을 것입니다. 경우에 따라 C# 컴파일러는 컴파일러를 더 간단하게 유지하는 근거로 거의 불필요한 코드를 생성하고 있습니다. 반복자 블록은 올바르게 잡기가 매우 까다로워 야합니다 (결국 블록 및 반복자 처리로 매우 복잡해질 수 있습니다).

나는 C# 컴파일러가 바보라고 주장 할 수있다. 런 타임에 의해 Jitte가있을 때이 코드가 매우 다르게 보일 수도 있습니다 (불쾌한 쓰레기는 생략됩니다).

어쨌든, 당신은 주 머신에 익숙할까요? C# (수율 재료)에 발전기를 쓰면 컴파일러 에게이 생성기를 상태 머신으로 구현하는 익명 유형을 방출하도록 지시합니다. 이것은 검증 가능한 멋진 공식적인 접근법입니다. 그것이 아마도 그것이하는 것처럼 보이는 이유 일 것입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top