risposta
Sì, il blocco finally
viene eseguito tuttavia il flusso lascia il blocco try
, sia raggiungendo la fine, restituendo o generando un'eccezione.
Dalla C# 4 spec, sezione 8.10:
le dichiarazioni di un blocco finally vengono sempre eseguiti quando il controllo lascia una prova dichiarazione. Questo è vero se il trasferimento del controllo avviene come risultato della normale esecuzione dello , come risultato dell'esecuzione di un'istruzione break, continue, goto o return, o come risultato di propagare un'eccezione dall'istruzione try.
(Sezione 8.10 ha molto più in dettaglio su questo, naturalmente.)
Si noti che il valore di ritorno è determinato prima il blocco finally viene eseguito, quindi se avete fatto queste cose:
int Test()
{
int result = 4;
try
{
return result;
}
finally
{
// Attempt to subvert the result
result = 1;
}
}
... il valore 4 verrà comunque restituito, non 1 - l'assegnazione nel blocco finally
non avrà alcun effetto.
Un blocco finally viene sempre eseguito e questo accadrà prima di ritornare dal metodo, quindi si può tranquillamente scrivere codice come questo:
try {
return "foo";
} finally {
// This will always be invoked
}
o se si sta lavorando con le risorse e getta:
using (var foo = GetFoo())
{
// foo is guaranteed to be disposed even if an exception is thrown
return foo.Bar();
}
Grazie per la risposta! – Liu
Alla fine i blocchi verranno eseguiti se si torna da try o si rilevano blocchi in C-Sharp?
SI
Se lo farà, Prima di tornare o dopo?
PRIMA
Con due passaggi la gestione delle eccezioni, che .NET eredita dalle finestre, non si può dire con precisione che il blocco finally viene eseguito prima che il controllo passa al chiamante.
Il blocco finally verrà eseguito dopo aver bloccato definitivamente i frame di chiamata più nidificati, e prima ancora blocchi e il blocco catch in frame di chiamata meno nidificati, che è coerente con il blocco finally in esecuzione prima di tornare. Ma tutti i filtri di eccezione tra il punto di lancio e il punto di cattura verranno eseguiti prima di qualsiasi blocco finale, il che significa che in presenza di un'eccezione, un codice chiamante può essere eseguito prima del blocco finale.
Quando il controllo lascia normalmente il blocco (nessuna eccezione generata), infine viene eseguito prima che il controllo ritorni al chiamante.
+1 perché vale la pena menzionare i filtri delle eccezioni ... ma anche con i filtri delle eccezioni, sicuramente il blocco finally è in esecuzione prima che il controllo ritorni al chiamante. È solo che i filtri delle eccezioni possono essere eseguiti anche prima. –
Bene, il controllo passa al filtro delle eccezioni del chiamante, quindi al blocco finally, quindi al gestore delle eccezioni del chiamante. Quindi il controllo passa al chiamante sia prima che dopo il blocco finale. –
Grazie per la tua risposta! – Liu
non che sia davvero di molto significato pratico ma il blocco finally non viene eseguito se si verifica una StackOverflowException o se si chiama System.Environment.FailFast (...) –
Naturalmente, il controllo non ritorna al chiamante affatto quei casi. Si potrebbe dire che il flusso * finisce * piuttosto che lasciare il blocco, così che la dichiarazione di Skeet continua a valere. –