Si un bloque finalmente arroja una excepción, ¿ qué sucede exactamente ?
Específicamente, qué sucede si la excepción se lanza a la mitad de un bloque finalmente. ¿Se invoca el resto de las declaraciones (después) en este bloque?
Soy consciente de que las excepciones se propagarán hacia arriba.
c#
exception
exception-handling
try-catch-finally
Jack Kada
fuente
fuente
Respuestas:
Esa excepción se propaga hacia arriba y hacia arriba, y se (puede) manejar en un nivel superior.
Su bloqueo final no se completará más allá del punto donde se produce la excepción.
Si el bloque finalmente se estaba ejecutando durante el manejo de una excepción anterior, entonces esa primera excepción se pierde.
fuente
ThreadAbortException
, entonces todo el bloque finalmente se terminará primero, ya que es una sección crítica.Para preguntas como estas, generalmente abro un proyecto de aplicación de consola vacía en Visual Studio y escribo un pequeño programa de muestra:
Cuando se ejecuta el programa, verá el orden exacto en el que
catch
yfinally
bloques son ejecutados. Tenga en cuenta que el código en el bloque finalmente después de que se lanza la excepción no se ejecutará (de hecho, en este programa de ejemplo, Visual Studio incluso le advertirá que ha detectado código inalcanzable):Observación adicional
Como señaló Michael Damatov,
try
se "comerá" una excepción del bloque si no lo maneja en uncatch
bloque (interno) . De hecho, en el ejemplo anterior, la excepción relanzada no aparece en el bloque de captura externo. Para aclarar aún más la siguiente muestra ligeramente modificada:Como puede ver en la salida, la excepción interna se "pierde" (es decir, se ignora):
fuente
finally
bloque (casi) siempre se ejecutará, esto también es válido en este caso para el bloque finalmente interno (solo pruebe el programa de muestra usted mismo (un bloque finalmente no se ejecutará en el caso de un no recuperable) excepción, por ejemplo, unaEngineExecutionException
, pero en tal caso su programa finalizará inmediatamente de todos modos)Si hay una excepción pendiente (cuando el
try
bloque tiene unfinally
pero nocatch
), la nueva excepción reemplaza a esa.Si no hay una excepción pendiente, funciona igual que lanzar una excepción fuera del
finally
bloque.fuente
catch
bloque que (re) emite una excepción.La excepción se propaga.
fuente
Fragmento rápido (y bastante obvio) para guardar la "excepción original" (arrojada en
try
bloque) y sacrificar la "excepción final" (arrojada enfinally
bloque), en caso de que la original sea más importante para usted:Cuando se ejecuta el código anterior, "Excepción original" se propaga por la pila de llamadas y se pierde "Finalmente excepción".
fuente
Tuve que hacer esto para detectar un error al intentar cerrar una transmisión que nunca se abrió debido a una excepción.
si se creó webRequest pero se produjo un error de conexión durante el
entonces el finalmente detectaría una excepción al tratar de cerrar conexiones que creía que estaban abiertas porque se había creado webRequest.
Si finalmente no tuviera un try-catch dentro, este código causaría una excepción no controlada mientras limpiaba el webRequest
a partir de ahí, el código saldría sin manejar adecuadamente el error que sucedió y, por lo tanto, causar problemas para el método de llamada.
Espero que esto ayude como ejemplo
fuente
Lanzar una excepción mientras otra excepción está activa dará como resultado que la primera excepción sea reemplazada por la segunda (más tarde) excepción.
Aquí hay un código que ilustra lo que sucede:
fuente
Hace unos meses también me enfrenté a algo como esto,
Para resolver tal problema, hice una clase de utilidad como
Y usado así
pero si quieres usar parámetros y tipos de retorno, esa es otra historia
fuente
La forma en que se manejan las excepciones lanzadas por CodeA y CodeB es la misma.
Una excepción lanzada en un
finally
bloque no tiene nada especial, trátela como la excepción lanzada por el código B.fuente
La excepción se propaga y debe manejarse a un nivel superior. Si la excepción no se maneja en el nivel superior, la aplicación se bloquea. La ejecución del bloque "finalmente" se detiene en el punto donde se produce la excepción.
Independientemente de si hay una excepción o no, el bloque "finalmente" está garantizado para ejecutarse.
Si el bloque "finalmente" se está ejecutando después de que se haya producido una excepción en el bloque try,
y si esa excepción no se maneja
y si el bloque finalmente arroja una excepción
Entonces se pierde la excepción original que ocurrió en el bloque try.
Gran artículo para detalles
fuente
Lanza una excepción;) Puede capturar esa excepción en alguna otra cláusula catch.
fuente