2009-08-01 13 views
11

Po eksperymentowaniu z blokiem iteratora zauważyłem, że wygenerowany kod IL nie jest tym, czego się spodziewam. Zamiast bloku try-finally generowany jest blok try-fault, którego nigdy nie widziałem. Zauważyłem, że kompilator nie pozwala mi używać słowa kluczowego fault w 'odręcznie' C#.Blok iteratora generuje błąd próbny w IL

Czy jest jakaś różnica między 2?

C# Kod:

static IEnumerable<string> ReadAllLines(string fileName) 
{ 
    using (var file = System.IO.File.OpenText(fileName)) 
    { 
     string s; 
     while ((s = file.ReadLine()) != null) 
     { 
      yield return s; 
     } 
    } 
} 

kod MSIL:

.method private hidebysig newslot virtual final instance bool MoveNext() cil managed 
{ 
    .override [mscorlib]System.Collections.IEnumerator::MoveNext 
    .maxstack 3 
    .locals init (
     [0] bool CS$1$0000, 
     [1] int32 CS$4$0001, 
     [2] string CS$0$0002, 
     [3] bool CS$4$0003) 
    L_0000: ldarg.0 

    // try body 

    L_008d: leave.s L_0097 
    L_008f: ldarg.0 
    L_0090: call instance void ConsoleApplication2.Program/<ReadAllLines>d__0::System.IDisposable.Dispose() 
    L_0095: nop 
    L_0096: endfinally 
    L_0097: nop 
    L_0098: ldloc.0 
    L_0099: ret 
    .try L_0000 to L_008f fault handler L_008f to L_0097 
} 

Ciekawa linia jest ostatnia linia IL gdzie procedura obsługi błędu jest określony, gdzie w normalnym try-w końcu zablokować w końcu określono obsługę.

+1

Dlaczego jest to oznaczone konkretnie przy użyciu .net-4.0? Czy ta zmiana między wersjami? –

Odpowiedz

8

Tak, blok finally zawsze wykonuje się po wyjściu z ramki. Blok błędu jest wykonywany tylko wtedy, gdy wyjątek zostanie usunięty poza ramką. Blok błędu w MoveNext zachowuje semantykę użycia dla przypadku wyjątku wyrzuconego z bloku try w iteratorze ReadAllLines. Niektóre inne mechanizmy muszą być w użyciu, aby zachować semantykę przy normalnym wyjściu z iteratora.

+0

Tak więc utylizacja w błędzie jest wywoływana tylko podczas obsługi wyjątku w części try. Regularne usuwanie jest obsługiwane przez metodę Dispose wygenerowanego IEnumeratora. –