2009-07-17 10 views
17

Se si esegue il codice qui sotto esegue in realtà la fine dopo ogni chiamata al goto:Perché questo "finally" viene eseguito?

int i = 0; 
Found: 
    i++; 
    try 
    { 
     throw new Exception(); 
    } 
    catch (Exception) 
    { 
     goto Found; 
    } 
    finally 
    { 
     Console.Write("{0}\t", i); 
    } 

Perché?

+12

-1 per l'utilizzo di GOTO –

+8

Non l'ho fatto nel codice di produzione. Era solo una situazione ipotetica. – Kredns

+1

Motivo principale per il basso voto: ho pensato che il suo tipo di noob domanda, dopo aver guadagnato oltre 4k punti !!! Mi dispiace ... :) –

risposta

28

Perché ti aspetti che non venga eseguito?

Se si tenta/catch/finally o try/finally block, infine il blocco viene eseguito indipendentemente dal codice che si può avere nel try o catch block most of the time.

Invece di goto, si consideri 'return'.

//imagine this try/catch/finally block is inside a function with return type of bool. 
try 
{ 
    throw new Exception(); 
} 
catch (Exception) 
{ 
    return false; //Let's say you put a return here, finally block still executes. 
} 
finally 
{ 
    Console.WriteLine("I am in finally!"); 
} 
+0

Suppongo di aver pensato che un goto avrebbe ignorato questo. – Kredns

+0

Nessun costrutto può sovrascrivere questo comportamento. 'goto'/'return'/qualsiasi altro costrutto che si possa immaginare. – SolutionYogi

+2

cosa succede se hai un 'return true;' nel blocco finally (rispetto al codice di esempio sopra). cosa viene restituito? il falso o il vero? –

2

Questo è di progettazione. Nel gestore delle eccezioni puoi prendere qualche azione specifica per eccezione. Nel blocco finally si dovrebbe fare la pulizia delle risorse - ecco perché il blocco finally viene sempre eseguito indipendentemente dal codice di gestione delle eccezioni.

3

Sembra ragionevole. Un blocco finally viene sempre eseguito dopo try o catch.

Analogamente

try 
{ 
    // do something 
    return; 
} 
finally 
{ 
    // do something else 
} 

sarà sempre eseguire il blocco finally. EDIT - ma vedi i commenti di Eric sopra.

0

Perché una dichiarazione finally si prevede di eseguire dopo aver lasciato il try (o catch quando un'eccezione viene catturato). Ciò include quando effettui la tua goto call.

37

Il testo che segue proviene dalla del linguaggio C# Specification (8.9.3 The goto statement)


Un'istruzione goto viene eseguita nel modo seguente:

  • Se l'istruzione goto esce uno o più blocchi try con associati infine ai blocchi, il controllo viene inizialmente trasferito al blocco finale dell'istruzione try più interna. Quando e se il controllo raggiunge il punto finale di un blocco finale, il controllo viene trasferito al blocco finale della successiva istruzione di prova allegata. Questo processo viene ripetuto fino a quando non sono stati eseguiti i blocchi finali di tutte le dichiarazioni di prova intervenienti.
  • Il controllo viene trasferito alla destinazione dell'istruzione goto.
+2

+1 per referenziare la specifica. –

+0

+1 per fare riferimento anche alle specifiche. –

+0

Dio! La specifica è piuttosto lunga ;-) – Kredns

1

Come si è detto, lo finally viene eseguito indipendentemente dal flusso del programma. Ovviamente, il blocco finally è facoltativo, quindi se non ne hai bisogno, non usarlo.

12

L'essenza delle risposte fornite - che quando il controllo lascia la regione protetta con qualsiasi mezzo, sia "ritorno", "goto", "interrompi", "continua" o "getta", viene eseguito "finalmente" - è corretta. Tuttavia, noto che quasi tutte le risposte dicono qualcosa come "il blocco finally funziona sempre". Il blocco finally NON viene sempre eseguito. Esistono molte situazioni in cui il blocco finally non viene eseguito.

Chi vuole provare ad elencarli tutti?

+0

Secondo la specifica "Le istruzioni di un blocco finally vengono sempre eseguite quando il controllo lascia una dichiarazione try. Questo è vero se il trasferimento del controllo avviene come risultato della normale esecuzione, come risultato dell'esecuzione un'istruzione break, continue, goto o return, o come risultato di propagare un'eccezione fuori dall'istruzione try. " Tuttavia, direi che uno StackOverflowException è uno, perché nulla può gestirlo per quanto posso vedere. –

+1

Colin, infatti, il punto chiave è QUANDO I FOGLI DI CONTROLLO. Se il controllo non parte, il blocco finally non viene eseguito! Ad esempio, la regione protetta da prova potrebbe contenere un ciclo infinito. –

+0

@Eric: ho completamente ricevuto questa domanda dal tuo post sul blog. Inoltre, non ho pensato a un ciclo infinito in un blocco try/catch – Kredns

0

Questo è il punto del blocco finally. Esegue sempre (praticamente).