2012-04-21 8 views
5

Sembra che faccia come per alcuni test iniziali, ma quello che mi piacerebbe sapere è se è garantito restituire o se in alcuni casi non può tornare? Questo è fondamentale per la mia applicazione, ma non ho ancora trovato un caso d'uso in cui non sarebbe tornato.
Mi piacerebbe avere esperienza in materia.Se torno da un blocco try/finally in C#, il codice in definitiva viene sempre eseguito?

+1

Alcune eccezioni non possono essere catturati come un overflow dello stack. –

+0

Vedi qui: http://stackoverflow.com/a/50627/5190 –

+0

Puoi superare il tuo scenario? Tieni presente che un programma può essere forzato. Dal titolo, sembra che tu stia chiedendo se provare {return; } infine {// mycode} eseguirà finalmente il codice. La risposta è no. –

risposta

10

Qualsiasi cosa in un blocco finally verrà sempre eseguita indipendentemente da ciò che accade all'interno dei blocchi try o catch. Non importa se restituisci il metodo o no.

L'unica eccezione è se il codice nel blocco finally genera un'eccezione, quindi smetterà di essere eseguito come qualsiasi altro blocco di codice.

Per quanto riguarda il goto, la risposta è ancora sì. Si consideri il codice seguente:

try 
{ 
    Console.WriteLine("Inside the Try"); 
    goto MyLabel; 
} 
finally 
{ 
    Console.WriteLine("Inside the Finally"); 
} 

MyLabel: 
    Console.WriteLine("After the Label"); 

L'output è questo:

All'interno della Prova

All'interno Infine

dopo l'etichetta

+0

anche se faccio un goto? – zorg

+0

'Thread.Sleep (-1)' :) – Ryan

+0

@zorg: [Sì, anche se fai un 'goto'.] (Http://ideone.com/a8LUJ) – Ryan

1

In caso di eccezioni fatali che terminano l'applicazione Infine il blocco non sarà b e chiamato. Include overflow dello stack, eccezioni durante il JIT dei metodi di chiamata, eccezioni irreversibili Runtime CLR insisde.

Come @mintech indica se l'applicazione si blocca all'interno del blocco, semplicemente non raggiungerà infine il blocco. Ciò include l'attesa di oggetti di sincronizzazione, deadlock infiniti o persino un'interfaccia utente che non ha un modo per chiuderla.

28

Ci sono un numero di imprecisioni nelle altre risposte.

Il controllo viene passato al blocco finally quando il controllo lascia il blocco try normalmente - ovvero, con un ritorno, goto, interruzione, continua o semplicemente cadendo dalla fine. Il controllo viene passato al blocco finally quando il controllo lascia il blocco try tramite un'eccezione che è stata rilevata da un blocco catch allegando.

In ogni altra circostanza non esiste la garanzia che verrà chiamato il codice nel blocco finally. In particolare:

  • Se il codice di blocco try entra in un ciclo infinito, o il filo è congelato e scongelato mai, allora la fine blocco di codice non viene mai chiamato.

  • Se il processo viene messo in pausa nel debugger e quindi viene ucciso in modo aggressivo, il blocco finally non viene mai chiamato. Se il processo esegue un fail-fast allora il blocco finally non viene mai chiamato.

  • Se il cavo di alimentazione viene estratto dal muro, il blocco finale non viene mai chiamato.

  • Se è un'eccezione generata senza un corrispondente blocco catch quindi se il blocco finally viene eseguito o non è un dettaglio di implementazione del runtime. Il runtime può scegliere qualsiasi comportamento in presenza di un'eccezione non rilevata. Entrambi "non esegui i blocchi finali" e "esegui i blocchi finali" sono esempi di "qualsiasi comportamento", quindi possono essere scelti entrambi. Tipicamente, ciò che fa il runtime è chiedere all'utente se vuole collegare un debugger prima che i blocchi finali vengano eseguiti; se l'utente dice no, allora i blocchi finali vengono eseguiti. Ma ancora: il runtime non è richiesto per farlo. Potrebbe fallire velocemente.

Non si può fare affidamento su blocchi finalmente chiamati. Se hai bisogno di una forte garanzia sull'esecuzione del codice, allora non dovresti scrivere una prova-finalmente, dovresti scrivere una regione di esecuzione vincolata . Scrivere correttamente un CER è uno dei compiti più difficili nella programmazione in C#, quindi studia attentamente la documentazione prima di provare a scrivere il codice.

Per inciso, un "fatto fun" circa GOTOS infine-bloccati è:

try { goto X; } finally { throw y; } 
X : Console.WriteLine("X"); 

X è un'etichetta irraggiungibile mirato da un raggiungibile goto! Quindi la prossima volta che sei a una festa puoi essere come "ehi, chiunque può fare un programma in C# che abbia un'etichetta irraggiungibile che è targata da un goto raggiungibile?" e vedrai chi alla festa ha letto le specifiche di raggiungibilità e chi no!

+0

Vorrei aggiungere bug: in runtime, sistema operativo, driver, hardware, ecc. Che ha causato il blocco di BSOD o PC. –

+0

@EricLippert Se outofMemory exception si verifica nel blocco try, penso che Finally non verrà eseguito. Sono corretto nel presupposto che? Per favore mi faccia sapere. – Sandeep

+3

Quindi la morale della storia è: non invitare mai Eric Lippert alle tue feste;) – Tergiver

4

ecco alcuni esempi:

Environment.FailFast()

 try 
     { 
      Console.WriteLine("Try"); 
      Environment.FailFast("Test Fail"); 

     } 
     catch (Exception) 
     { 
      Console.WriteLine("catch"); 
     } 
     finally 
     { 
      Console.WriteLine("finally"); 
     } 

L'uscita è solo "Prova"

StackOverflow

 try 
     { 
      Console.WriteLine("Try"); 
      Rec(); 
     } 
     catch (Exception) 
     { 
      Console.WriteLine("catch"); 
     } 
     finally 
     { 
      Console.WriteLine("finally"); 
     } 

Dove Rec è:

private static void Rec() 
    { 
     Rec(); 
    } 

L'uscita è solo "Prova" e il processo termina per StackOverflow.

eccezione unhanded

 try 
     { 
      Console.WriteLine("Try"); 
      throw new Exception(); 
     } 
     finally 
     { 
      Console.WriteLine("finally"); 
     } 
Problemi correlati