Pergunta

Depois de experimentar com um bloco iterador notei o código IL gerado não é o que eu esperava que fosse. Em vez de um try-finally bloquear um bloco try-falha é gerada, que eu nunca vi. Notei que o compilador não permite que eu use a falha de palavras-chave em 'manuscrito' C #.

Existe alguma diferença entre o 2?

C # código:

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
}

A linha interessante é a última linha do IL onde um manipulador de falhas for especificado, onde em um normal de try-finally bloquear uma finalmente é especificado manipulador.

Foi útil?

Solução

Sim, um bloco finally sempre executa no quadro saída. Um bloco de culpa executa somente se uma exceção é desenrolado após o quadro. O bloco de falha no MoveNext preserva as usando semântica para o caso de uma exceção lançada a partir do bloco try do iterador ReadAllLines. Algum outro mecanismo deve estar em uso para preservar os que usam a semântica de saída normal do iterador.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top