2009-10-16 8 views
17

Suponga que tiene el siguiente código:Manejo de excepciones: ¿Finalmente se ejecuta después del lanzamiento?

En vez de hacer:

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 

me gustaría hacer:

Try 
    ' 
    ' Initialize some objects 
    ' 

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

Así que mi simple pregunta es: En caso de una excepción es el finalmente se llegó al bloque incluso si hay un lanzamiento de algunas líneas antes?

[EDITAR] Gracias por su respuesta rápida.

En la primera línea, habrá NullReference-, COM- y FileNotFound-Exceptions, creo.

Ok, voy a ir a por este código:

Try 
    ' 
    ' Initialize some objects 
    ' 

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

Todo lo mejor!

Inno

+2

No debe escribir 'Throw e' pero solo' Throw'. De lo contrario, restablece el seguimiento de la pila de excepciones, por lo que pierde la información sobre dónde se originó la excepción inicialmente –

Respuesta

25

Así que mi pregunta es sencilla: En caso de una excepción es el bloque finally alcanzó incluso si hay un tiro algunas líneas antes?

Sí. El Finally block es siempre1) ejecutado y existe precisamente para la limpieza. En su código, elimine el bloque Catch, no hace nada. Peor aún, en realidad destruye la traza de la pila porque no vuelves a lanzar la excepción original, sino que lanzas una nueva.

Si realmente necesita un bloque Catch que luego re-lanza la excepción, utilice la siguiente:

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

1): Emptor de la advertencia: hay algunas excepciones como StackOverflowException (cómo montaje ...) que requieren una atención especial y no pueden disparar el bloque Finally. Manejarlos correctamente es generalmente bastante difícil.

+1

Konrad: finalmente no siempre se ejecuta. No se ejecutará cuando tenga una excepción OutOfMemoryException, por ejemplo. –

+0

@ Pete: correcto, pero estos son casos específicos (pero debería haberlos mencionado). –

+1

@Pete: ¿No te refieres a StackOverflowException? Es muy fácil hacer una prueba donde finalmente se ejecuta en caso de una OutOfMemoryException. –

0

Sí lo hace, finalmente se ejecuta en cualquier caso. (solo hay unas pocas excepciones: Response.Redirect y algunos casos con subprocesamiento múltiple)

5

No, NO se garantiza que se ejecute. Existen ciertas excepciones, como StockOverflowException y OutOfMemoryException, en las que no se garantiza la ejecución de un bloque finally.

1

En casi todos los casos, a Finally se ejecutará en un bloque Try/Catch (excepciones notables incluso cuando se produce una excepción StackOverflowException o OutOfMemoryException). Sin embargo, tengo curiosidad, por qué no probaste esto por ti mismo. Una forma valiosa de aprender cosas es realmente probarlas por ustedes mismos - después de todo, podrían terminar aceptando una respuesta que es incorrecta o engañosa, y trabajarán bajo esta falsedad a partir de ese momento.

+1

Probé esto, pero mi depurador se detuvo en el lanzamiento. Leí la documentación y no encontré una pista para mi pregunta. Hice estas preguntas para obtener respuestas que pertenecen directamente a mi pregunta y que pertenecen indirectamente a ella (como sugerencias como "finalmente no se ejecuta bajo circunstancias especiales"). – Inno

1

NOTA: El método System.Environment.FastFail eliminó inmediatamente el proceso/subproceso actual, sin ejecutar finalmente las secciones.