2009-07-17 20 views
17

Si ejecuta el código de abajo que en realidad ejecuta el fin después de cada llamada al Goto:¿Por qué se ejecuta este "finalmente"?

int i = 0; 
Found: 
    i++; 
    try 
    { 
     throw new Exception(); 
    } 
    catch (Exception) 
    { 
     goto Found; 
    } 
    finally 
    { 
     Console.Write("{0}\t", i); 
    } 

¿Por qué?

+12

-1 para usar GOTO –

+8

No hice esto en el código de producción. Fue solo una situación hipotética. – Kredns

+1

Motivo principal para votar: pensé que era una pregunta novata, ¡después de ganar más de 4k puntos! Lo siento ... :) –

Respuesta

28

¿Por qué esperas que no se ejecute?

Si tiene try/catch/finally o try/finally, bloque finally se ejecuta no importa qué código que pueda tener en el try o captura bloque most of the time.

En lugar de goto, considere 'devolver'.

//imagine this try/catch/finally block is inside a function with return type of bool. 
try 
{ 
    throw new Exception(); 
} 
catch (Exception) 
{ 
    return false; //Let's say you put a return here, finally block still executes. 
} 
finally 
{ 
    Console.WriteLine("I am in finally!"); 
} 
+0

Creo que pensé que un goto podría anular esto. – Kredns

+0

Ninguna construcción puede anular este comportamiento. 'goto'/'return'/cualquier otra construcción que puedas imaginar. – SolutionYogi

+2

qué pasa si tienes un 'return true;' en el bloque finally (contra el código de ejemplo anterior). ¿Qué se devuelve? lo falso o lo verdadero? –

2

Eso es por diseño. En el controlador de excepciones, puede realizar alguna acción específica de excepción. En el bloque finally, deberías hacer la limpieza de los recursos, por eso el bloque finally siempre se ejecuta sin importar el código de manejo de excepciones.

3

Parece razonable. Un bloque finally siempre se ejecuta después del try o el catch.

Del mismo modo

try 
{ 
    // do something 
    return; 
} 
finally 
{ 
    // do something else 
} 

siempre se ejecutará el bloque finally. EDITAR - pero vea los comentarios de Eric arriba.

0

Porque se espera que se ejecute una instrucción finally después de salir de try (o catch cuando se detecta una excepción). Esto incluye cuando realizas tu llamada por puntos.

37

El siguiente texto proviene de la C# Language Specification (8.9.3 The goto statement)


Una instrucción goto se ejecuta de la siguiente manera:

  • Si la instrucción goto sale de uno o más bloques try con bloques finally asociados, el control se transfiere inicialmente al bloque finally de la instrucción try más interna. Cuando y si el control alcanza el punto final de un bloque finally, el control se transfiere al bloque finally de la próxima instrucción try adjunta. Este proceso se repite hasta que se hayan ejecutado finalmente los bloques de todas las declaraciones try intermedias.
  • El control se transfiere al objetivo de la instrucción goto.
+2

+1 para hacer referencia a la especificación. –

+0

+1 para hacer referencia a la especificación, también. –

+0

Dios! La especificación es bastante larga ;-) – Kredns

1

Como han mencionado las personas, finally se ejecuta sin importar el flujo del programa. Por supuesto, el bloque finally es opcional, por lo que si no lo necesita, no lo use.

12

La esencia de las respuestas dadas: cuando el control sale de la región protegida por cualquier medio, ya sea "retorno", "goto", "romper", "continuar" o "lanzar", se ejecuta "finalmente" - es correcto. Sin embargo, observo que casi todas las respuestas dicen algo como "el bloque finally siempre se ejecuta". El bloque finally NO siempre se ejecuta. Hay muchas situaciones en las que el bloque finally no se ejecuta.

¿Quién quiere intentar enumerarlos a todos?

+0

De acuerdo con la especificación "Las instrucciones de un bloque finally siempre se ejecutan cuando el control deja una instrucción try. Esto es así ya sea que la transferencia de control ocurra como resultado de una ejecución normal, como resultado de la ejecución una sentencia break, continue, goto o return, o como resultado de propagar una excepción fuera de la instrucción try ". Sin embargo, diría que una StackOverflowException es una, porque nada puede lidiar con ella hasta donde yo pueda ver. –

+1

Colin, de hecho, el punto clave es CUANDO EL CONTROL DEJA. Si el control no se va, ¡entonces el bloque finally no se ejecuta! La región try-protected podría contener un bucle infinito, por ejemplo. –

+0

@Eric: Obtuve esta pregunta totalmente en tu publicación de blog. Tampoco pensé en un ciclo infinito en un bloque try/catch – Kredns

0

Ese es el punto del bloque finally. Siempre se ejecuta (bastante).

Cuestiones relacionadas