Domanda

Dopo aver sperimentato un blocco iteratore ho notato che il codice IL generato non è quello che mi aspetto che sia. Invece di un blocco try-finally viene generato un blocco try-fault, che non ho mai visto. Ho notato che il compilatore non mi consente di utilizzare la parola chiave fault in C # "scritto a mano".

C'è qualche differenza tra i 2?

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

Codice 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 riga interessante è l'ultima riga dell'IL in cui è specificato un gestore degli errori, in cui in un normale blocco try-finally è specificato un gestore infine.

È stato utile?

Soluzione

Sì, un blocco Infine viene sempre eseguito all'uscita del frame. Un blocco errori viene eseguito solo se un'eccezione viene srotolata oltre il frame. Il blocco errori in MoveNext conserva la semantica di utilizzo nel caso di un'eccezione generata dal blocco try dell'iteratore ReadAllLines. È necessario utilizzare qualche altro meccanismo per preservare l'utilizzo della semantica in uscita normale dall'iteratore.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top