2009-08-01 14 views
11

Después de experimentar con un bloque iterador noté que el código IL generado no es lo que espero que sea. En lugar de un bloque try-finally se genera un bloque try-fault, que nunca he visto. Noté que el compilador no me permite usar la palabra clave de falla en 'C' manuscrita.El bloque de iterador genera try-fault en IL

¿Hay alguna diferencia entre los 2?

código C#:

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

código 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 
} 

La línea interesante es la última línea de la IL donde se especifica un administrador de fallos, donde en una normal de try-finally una finalmente se especifica el manejador.

+1

¿Por qué está etiquetado específicamente con .net-4.0? ¿Esto cambió entre versiones? –

Respuesta

8

Sí, un bloque Finalmente siempre se ejecuta al salir del marco. Un bloque de falla se ejecuta solo si se desenrolla una excepción más allá del marco. El bloque de fallas en MoveNext conserva la semántica de uso para el caso de una excepción lanzada desde el bloque try del iterador ReadAllLines. Algún otro mecanismo debe estar en uso para preservar la semántica de uso en la salida normal del iterador.

+0

Por lo tanto, solo se llama a Dispose in the fault cuando se maneja una excepción en la parte try. Y el desecho regular se maneja mediante el método Dispose del IEnumerator generado. –