2009-10-16 2 views
17

Si supponga di avere il seguente codice:Gestione delle eccezioni: viene infine eseguito dopo il lancio?

Invece di fare:

Try 
    ' 
    ' Initialize some objects 
    ' 

    ' 
    ' do something that fails 
    ' 

    ' 
    ' Clean up-code that gets not reached because exception 
    ' 
Catch e As Exception 
    ' 
    'Clean up initialized objects 
    ' 

    Throw e 
End Try 

Vorrei fare:

Try 
    ' 
    ' Initialize some objects 
    ' 

    ' 
    ' do something that fails 
    ' 
Catch e As Exception 
    Throw e 
Finally 
    ' 
    'Clean up initialized objects 
    ' 
End Try 

Quindi la mia semplice domanda è: In caso di eccezione è il finalmente blocco raggiunto anche se c'è un lancio di alcune linee prima?

[EDIT] Grazie per le risposte veloci.

Nella prima riga ci saranno NullReference-, COM- e FileNotFound-Exceptions.

Ok, andrò per questo codice:

Try 
    ' 
    ' Initialize some objects 
    ' 

    ' 
    ' do something that fails 
    ' 
Catch e As Exception  ' or just "Catch"??   
    Throw 
Finally 
    ' 
    'Clean up initialized objects 
    ' 
End Try 

Tutto il meglio!

Inno

+2

Non si dovrebbe scrivere "Getta e' ma solo" Getta ". Altrimenti, si ripristina la traccia dello stack di eccezioni, quindi si perdono le informazioni su dove inizialmente è stata sollevata l'eccezione –

risposta

25

Quindi la mia semplice domanda è: In caso di eccezione è il blocco finally raggiunto, anche se v'è un tiro alcune linee prima?

Sì. Il Finally block è sempre1) eseguito ed esiste esattamente per la pulizia. Nel codice, rimuovere il blocco Catch, non fa nulla. Peggio ancora, in realtà distrugge la traccia dello stack perché non rilanciate l'eccezione originale, ne lanciate una nuova.

Se davvero bisogno di un blocco Catch che poi ri-genera l'eccezione, utilizzare il seguente:

Catch e As XyzException 
    ' … do some stuff. ' 
    Throw 
End Try 

1): Caveat emptor: ci sono alcune eccezioni, come StackOverflowException (come adattamento ...) che richiedono un'attenzione speciale e potrebbero non attivare il blocco Finally. Gestirli correttamente è solitamente piuttosto difficile.

+1

Konrad - Finalmente non viene sempre eseguito. Non verrà eseguito se si dispone di OutOfMemoryException, ad esempio. –

+0

@Pete: giusto, ma questi sono casi limite specifici (ma avrei dovuto menzionarli). –

+1

@Pete: non intendi StackOverflowException. È facile fare un test dove finalmente viene eseguito in caso di OutOfMemoryException. –

0

Sì, finalmente viene eseguito in ogni caso. (ci sono solo poche eccezioni - Response.Redirect e alcuni casi con multithreading)

5

No, NON è garantito l'esecuzione. Esistono alcune eccezioni, ad esempio StockOverflowException e OutOfMemoryException, in cui l'esecuzione di un blocco finally non è garantita.

1

In quasi tutti i casi, a Finally verrà eseguito in un blocco Try/Catch (eccezioni notevoli incluso quando si verificano StackOverflowException o OutOfMemoryException). Sono curioso però, perché non l'hai provato per te stesso. Un modo valido per imparare le cose è provarle davvero per voi stessi - dopotutto, potreste finire per accettare una risposta che è sbagliata o fuorviante, e da quel momento in poi vi affaticherete con questa falsità.

+1

Ho provato questo, ma il mio debugger si è fermato al lancio. Ho letto la documentazione e non ho trovato un suggerimento per la mia domanda. Ho fatto queste domande per ottenere risposte che appartengono direttamente alla mia domanda e che appartengono indirettamente ad essa (come suggerimenti come "finalmente è in circostanze speciali non eseguite"). – Inno

1

NOTA: il metodo System.Environment.FastFail è stato killare il processo/thread corrente immediatamente, senza eseguire infine le sezioni.