try {
// Do stuff
}
catch (Exception e) {
throw;
}
finally {
// Clean up
}
Nel blocco sopra quando viene chiamato il blocco finally? Prima del lancio di eo viene infine chiamato e poi catturato?
try {
// Do stuff
}
catch (Exception e) {
throw;
}
finally {
// Clean up
}
Nel blocco sopra quando viene chiamato il blocco finally? Prima del lancio di eo viene infine chiamato e poi catturato?
Risposte:
Verrà richiamato dopo la rilancio di e (ovvero dopo l'esecuzione del blocco catch)
modificandolo 7 anni dopo, una nota importante è che se enon viene catturato da un blocco try / catch nello stack di chiamate o gestito da un gestore di eccezioni globale, il finallyblocco potrebbe non essere mai eseguito.
finallynon viene eseguito se l'eccezione generata nel precedente catchnon è mai catturato in un esterno try- catchblocco!
Perché non provarlo:
outer try
inner try
inner catch
inner finally
outer catch
outer finally
con codice (formattato per spazio verticale):
static void Main() {
try {
Console.WriteLine("outer try");
DoIt();
} catch {
Console.WriteLine("outer catch");
// swallow
} finally {
Console.WriteLine("outer finally");
}
}
static void DoIt() {
try {
Console.WriteLine("inner try");
int i = 0;
Console.WriteLine(12 / i); // oops
} catch (Exception e) {
Console.WriteLine("inner catch");
throw e; // or "throw", or "throw anything"
} finally {
Console.WriteLine("inner finally");
}
}
outer try inner try inner catch Unhandled Exception: System.DivideByZeroException...
Dopo aver letto tutte le risposte qui sembra che la risposta finale è dipende :
Se si rilancia un'eccezione all'interno del blocco catch e quell'eccezione viene catturata all'interno di un altro blocco catch, tutto viene eseguito in base alla documentazione.
Tuttavia, se l'eccezione re-trown non viene gestita, finalmente non viene mai eseguita.
Ho provato questo esempio di codice in VS2010 con C # 4.0
static void Main()
{
Console.WriteLine("Example 1: re-throw inside of another try block:");
try
{
Console.WriteLine("--outer try");
try
{
Console.WriteLine("----inner try");
throw new Exception();
}
catch
{
Console.WriteLine("----inner catch");
throw;
}
finally
{
Console.WriteLine("----inner finally");
}
}
catch
{
Console.WriteLine("--outer catch");
// swallow
}
finally
{
Console.WriteLine("--outer finally");
}
Console.WriteLine("Huzzah!");
Console.WriteLine();
Console.WriteLine("Example 2: re-throw outside of another try block:");
try
{
Console.WriteLine("--try");
throw new Exception();
}
catch
{
Console.WriteLine("--catch");
throw;
}
finally
{
Console.WriteLine("--finally");
}
Console.ReadLine();
}
Ecco l'output:
Esempio 1: ri-lanciare all'interno di un altro blocco try:
--outer try
---- inner try
---- inner catch
---- inner finally
--outer catch
--outer finalmente
Huzzah!Esempio 2: rilancia all'esterno di un altro blocco try:
--try
--catchEccezione non gestita: System.Exception: è stata generata un'eccezione del tipo "System.Exception".
at ConsoleApplication1.Program.Main () in C: \ local source \ ConsoleApplication1 \ Program.cs: riga 53
Il tuo esempio si comporterebbe in modo identico a questo codice:
try {
try {
// Do stuff
} catch(Exception e) {
throw e;
}
} finally {
// Clean up
}
Come nota a margine, se intendi davvero throw e;(ovvero, getta la stessa eccezione che hai appena catturato), è molto meglio fare semplicemente throw;, poiché ciò manterrà la traccia dello stack originale invece di crearne una nuova.
finallyblocco infatti verrà eseguito dopo il catchblocco (anche se il blocco catch rinnova l'eccezione), che è ciò che il mio frammento sta cercando di illustrare.
tryblocco di quella la mia risposta ha un "try-catch". Sto cercando di spiegare il comportamento del costrutto in 3 parti usando due costrutti in 2 parti. Non vedo alcun segno di un secondo tryblocco nella domanda originale, quindi non capisco dove lo stai ottenendo.
Se esiste un'eccezione non gestita all'interno di un blocco del gestore catch, il blocco finally viene chiamato esattamente zero volte
static void Main(string[] args)
{
try
{
Console.WriteLine("in the try");
int d = 0;
int k = 0 / d;
}
catch (Exception e)
{
Console.WriteLine("in the catch");
throw;
}
finally
{
Console.WriteLine("In the finally");
}
}
Produzione:
C: \ Users \ Administrator \ documenti \ TestExceptionNesting \ bin \ Release> TestExceptionNesting.exe
nel tentativo
nella cattura
Eccezione non gestita: System.DivideByZeroException: tentativo di dividere per zero. at TestExceptionNesting.Program.Main (String [] args) in C: \ utenti \ amministratore \ documenti \ TestExceptionNesting \ TestExceptionNesting.cs: riga 22
C: \ Users \ amministratore bin \ release \ documenti \ TestExceptionNesting \>
Mi è stata posta questa domanda oggi durante un'intervista e l'intervistatore ha continuato a tornare "sei sicuro che finalmente non viene chiamato?" Non ero sicuro che si trattasse di una domanda trabocchetto o che l'intervistatore avesse in mente qualcos'altro e abbia scritto il codice sbagliato per il debug, quindi sono tornato a casa e l'ho provato (costruisci e corri, nessuna interazione con il debugger), solo per pensare riposo.
Testando con un'applicazione console C #, il codice finally è stato eseguito dopo il lancio dell'eccezione: la "finestra di dialogo Errore applicazione" esisteva e dopo aver scelto l'opzione "Chiudi il programma", il blocco finally è stato eseguito nella finestra della console. Ma impostando il punto di rottura all'interno del blocco di codice finalmente, non riesco mai a colpirlo. Il debugger continua a fermarsi all'istruzione di lancio. Ecco il mio codice di prova:
class Program
{
static void Main(string[] args)
{
string msg;
Console.WriteLine(string.Format("GetRandomNuber returned: {0}{1}", GetRandomNumber(out msg), msg) == "" ? "" : "An error has occurred: " + msg);
}
static int GetRandomNumber(out string errorMessage)
{
int result = 0;
try
{
errorMessage = "";
int test = 0;
result = 3/test;
return result;
}
catch (Exception ex)
{
errorMessage = ex.Message;
throw ex;
}
finally
{
Console.WriteLine("finally block!");
}
}
}
Debug in VS2010 - .NET Framework 4.0