Pregunta

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'.

¿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<*>,
        [1] int32 CS$4$0001,
        [2] string CS<*>$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 manejador de fallas, donde en un bloque normal de prueba-finalmente se especifica un manejador finalmente.

¿Fue útil?

Solución

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

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top