Question

Après avoir expérimenté un bloc itérateur, j’ai remarqué que le code IL généré n’était pas ce que j’attendais. Au lieu d'un bloc try-finally, un bloc try-fault est généré, ce que je n'ai jamais vu auparavant. J'ai remarqué que le compilateur ne m'autorisait pas à utiliser le mot clé fault dans 'C # manuscrit'.

Y at-il une différence entre le 2?

Code 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;
        }
    }
}

Code 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 ligne intéressante est la dernière ligne de l’IL où un gestionnaire de fautes est spécifié. Dans un bloc try-finally normal, un gestionnaire de final est spécifié.

Était-ce utile?

La solution

Oui, un bloc Finally est toujours exécuté à la sortie du cadre. Un bloc d’erreur ne s’exécute que si une exception est levée au-delà de l’image. Le bloc de défauts dans MoveNext conserve la sémantique d'utilisation dans le cas d'une exception levée à partir du bloc try de l'itérateur ReadAllLines. Un autre mécanisme doit être utilisé pour préserver la sémantique d’utilisation lors de la sortie normale de l’itérateur.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top