try {
// Do stuff
}
catch (Exception e) {
throw;
}
finally {
// Clean up
}
En el bloque anterior, ¿cuándo se llama el bloque finalmente? Antes del lanzamiento de e o finalmente se llama y luego atrapar?
try {
// Do stuff
}
catch (Exception e) {
throw;
}
finally {
// Clean up
}
En el bloque anterior, ¿cuándo se llama el bloque finalmente? Antes del lanzamiento de e o finalmente se llama y luego atrapar?
Respuestas:
Se llamaría después de que e se vuelva a lanzar (es decir, después de que se ejecute el bloque catch)
editando esto 7 años después: una nota importante es que si eun bloque try / catch no lo atrapa más arriba en la pila de llamadas o lo maneja un controlador de excepción global, entonces el finallybloque puede nunca ejecutarse en absoluto.
finallyno se ejecuta si la excepción lanzada en el anterior catchnunca es atrapado en una externa try- catchbloque!
¿Por qué no probarlo?
outer try
inner try
inner catch
inner finally
outer catch
outer finally
con código (formateado para espacio vertical):
static void Main() {
try {
Console.WriteLine("outer try");
DoIt();
} catch {
Console.WriteLine("outer catch");
// swallow
} finally {
Console.WriteLine("outer finally");
}
}
static void DoIt() {
try {
Console.WriteLine("inner try");
int i = 0;
Console.WriteLine(12 / i); // oops
} catch (Exception e) {
Console.WriteLine("inner catch");
throw e; // or "throw", or "throw anything"
} finally {
Console.WriteLine("inner finally");
}
}
outer try inner try inner catch Unhandled Exception: System.DivideByZeroException...
Después de leer todas las respuestas aquí, parece que la respuesta final es : depende :
Si vuelve a lanzar una excepción dentro del bloque catch, y esa excepción se captura dentro de otro bloque catch, todo se ejecuta de acuerdo con la documentación.
Sin embargo, si la excepción re-trown no se maneja, finalmente nunca se ejecuta.
Probé este ejemplo de código en VS2010 con C # 4.0
static void Main()
{
Console.WriteLine("Example 1: re-throw inside of another try block:");
try
{
Console.WriteLine("--outer try");
try
{
Console.WriteLine("----inner try");
throw new Exception();
}
catch
{
Console.WriteLine("----inner catch");
throw;
}
finally
{
Console.WriteLine("----inner finally");
}
}
catch
{
Console.WriteLine("--outer catch");
// swallow
}
finally
{
Console.WriteLine("--outer finally");
}
Console.WriteLine("Huzzah!");
Console.WriteLine();
Console.WriteLine("Example 2: re-throw outside of another try block:");
try
{
Console.WriteLine("--try");
throw new Exception();
}
catch
{
Console.WriteLine("--catch");
throw;
}
finally
{
Console.WriteLine("--finally");
}
Console.ReadLine();
}
Aquí está la salida:
Ejemplo 1: volver a tirar dentro de otro bloque de prueba:
--probar exterior
---- prueba
interna
---- captura interna ---- interior finalmente
- captura
externa --alterno finalmente
¡Huzzah!Ejemplo 2: volver a lanzar fuera de otro bloque try:
--try
--catchExcepción no controlada: System.Exception: se produjo una excepción del tipo 'System.Exception'.
en ConsoleApplication1.Program.Main () en C: \ local source \ ConsoleApplication1 \ Program.cs: línea 53
Su ejemplo se comportaría de manera idéntica a este código:
try {
try {
// Do stuff
} catch(Exception e) {
throw e;
}
} finally {
// Clean up
}
Como nota al margen, si realmente quiere decir throw e;(es decir, lanzar la misma excepción que acaba de atrapar), es mucho mejor hacerlo throw;, ya que eso preservará el rastro original de la pila en lugar de crear uno nuevo.
finallybloque se ejecutará después del catchbloque (incluso si el bloque catch vuelve a generar la excepción), que es lo que mi fragmento está tratando de ilustrar.
trybloque de mi respuesta tiene un "try-catch". Estoy tratando de explicar el comportamiento de la construcción de 3 partes usando dos construcciones de 2 partes. No veo ningún signo de un segundo trybloque en la pregunta original, así que no entiendo de dónde lo sacas.
Si hay una excepción no controlada dentro de un bloque controlador de captura, el bloque finalmente se llama exactamente cero veces
static void Main(string[] args)
{
try
{
Console.WriteLine("in the try");
int d = 0;
int k = 0 / d;
}
catch (Exception e)
{
Console.WriteLine("in the catch");
throw;
}
finally
{
Console.WriteLine("In the finally");
}
}
Salida:
C: \ usuarios \ administrador \ documentos \ TestExceptionNesting \ bin \ Release> TestExceptionNesting.exe
en el intento
en la captura
Excepción no controlada: System.DivideByZeroException: intento de dividir por cero. en TestExceptionNesting.Program.Main (String [] args) en C: \ users \ administrador \ documentos \ TestExceptionNesting \ TestExceptionNesting.cs: línea 22
C: \ usuarios \ administrador \ documentos \ TestExceptionNesting \ bin \ release>
Me hicieron esta pregunta hoy en una entrevista y el entrevistador continuó diciendo "¿estás seguro de que finalmente no me llamen?" No estaba seguro de si se trataba de una pregunta capciosa o si el entrevistador tenía algo más en mente y escribió el código incorrecto para que lo depurara, así que llegué a casa y lo intenté (compilar y ejecutar, sin interacción del depurador), solo para pensar descanso.
Al probar con una aplicación de consola C #, el código finalmente se ejecutó después de que se lanzó la excepción: existió el "Diálogo de error de la aplicación" y después de elegir la opción "Cerrar el programa", el bloque finalmente se ejecutó en esa ventana de consola. Pero estableciendo el punto de ruptura dentro del bloque de código finalmente, nunca puedo golpearlo. El depurador sigue deteniéndose en la declaración de lanzamiento. Aquí está mi código de prueba:
class Program
{
static void Main(string[] args)
{
string msg;
Console.WriteLine(string.Format("GetRandomNuber returned: {0}{1}", GetRandomNumber(out msg), msg) == "" ? "" : "An error has occurred: " + msg);
}
static int GetRandomNumber(out string errorMessage)
{
int result = 0;
try
{
errorMessage = "";
int test = 0;
result = 3/test;
return result;
}
catch (Exception ex)
{
errorMessage = ex.Message;
throw ex;
}
finally
{
Console.WriteLine("finally block!");
}
}
}
Depuración en VS2010 - .NET Framework 4.0