2012-04-21 21 views
5

Parece que lo hace según algunas pruebas iniciales, pero lo que me gustaría saber es si es garantizado para devolver o si en algunos casos no puede devolver? Esto es crítico para mi aplicación, pero aún no he encontrado un caso de uso donde no vuelva.
Me gustaría obtener experiencia en el tema.Si regreso de un bloque try/finally en C# ¿el código finalmente se ejecuta?

+1

Algunas excepciones no pueden ser capturados como un desbordamiento de pila. –

+0

Consulte aquí: http://stackoverflow.com/a/50627/5190 –

+0

¿Puede resolver su situación? Tenga en cuenta que un programa se puede cancelar por la fuerza. Del título, parece que estás preguntando si intentas {return; } finally {// mycode} ejecutará el código finalmente. La respuesta es no. –

Respuesta

10

Cualquier cosa en un bloque finally siempre se ejecutará independientemente de lo que ocurra dentro de los bloques try o catch. No importa si regresas del método o no.

La única excepción a esto es si el código en el bloque finally arroja una excepción, y luego dejará de ejecutarse como cualquier otro bloque de código.

En cuanto a goto, la respuesta es sí. Considere el siguiente código:

try 
{ 
    Console.WriteLine("Inside the Try"); 
    goto MyLabel; 
} 
finally 
{ 
    Console.WriteLine("Inside the Finally"); 
} 

MyLabel: 
    Console.WriteLine("After the Label"); 

La salida producida es la siguiente:

Dentro de la Trata

Dentro del último

Después de la etiqueta

+0

incluso si hago un goto? – zorg

+0

'Thread.Sleep (-1)' :) – Ryan

+0

@zorg: [Sí, incluso si haces un 'goto'.] (Http://ideone.com/a8LUJ) – Ryan

1

En caso de Excepciones fatales que terminan la aplicación Finalmente el bloqueo no b e llamado. Incluye desbordamiento de pila, excepciones durante JIT de métodos para llamar, excepciones fatales insisde tiempo de ejecución de CLR.

Como @mintech señala si la aplicación se bloquea dentro del bloque, simplemente no llegará al bloque. Esto incluye la espera de objetos de sincronización, interbloqueos bucles infinitos o incluso interfaz de usuario que no tiene forma de cerrarlo.

28

Hay una serie de inexactitudes en las otras respuestas.

El control se pasa al bloque finally cuando el control sale del bloque try normalmente - es decir, mediante un retorno, goto, break, continue o simplemente cayendo del extremo. El control se pasa al bloque finally cuando el control abandona el bloque try a través de una excepción que ha sido capturada por un bloque catch catch.

En cualquier otra circunstancia no hay garantía que se llamará el código en el bloque finally. En particular:

  • Si el código de bloque try entra en un bucle infinito, o el hilo es congelado y nunca sin congelar, entonces el bloque finally código nunca es llamado.

  • Si el proceso se detiene en el depurador y luego se elimina agresivamente, entonces nunca se llama al bloque finally. Si el proceso falla, entonces nunca se llama al bloque finally.

  • Si el cable de alimentación se saca de la pared, entonces nunca se llama al bloque finally.

  • Si hay una excepción lanzada sin un bloque catch correspondiente continuación, si el bloque finally se ejecuta o no, es un detalle de implementación del tiempo de ejecución. El tiempo de ejecución puede elegir cualquier comportamiento cuando hay una excepción no detectada. Ambos "no ejecutan los bloques finally" y "do run the finally blocks" son ejemplos de "cualquier comportamiento", por lo que cualquiera puede ser elegido. Por lo general, lo que hace el tiempo de ejecución es preguntar al usuario si desea adjuntar un depurador antes de ejecutar finalmente los bloques; si el usuario dice que no, entonces los bloques finalmente se ejecutan. Pero otra vez: el tiempo de ejecución no es requiere para hacer eso. Podría simplemente fallar rápidamente.

No puede confiar en que finalmente se llamen siempre los bloques. Si necesita una gran garantía sobre la ejecución del código, entonces no debería estar escribiendo una prueba; por último, debe escribir una región de ejecución restringida. Escribir una CER correctamente es una de las tareas más difíciles en la programación C#, así que estudie la documentación cuidadosamente antes de intentar escribir el código.

Por cierto, un "hecho de la diversión" sobre GOTOS finalmente bloqueados-es:

try { goto X; } finally { throw y; } 
X : Console.WriteLine("X"); 

X es una etiqueta inalcanzable targetted alcanzable por un Goto! Así que la próxima vez que estés en una fiesta puedes decir "oigan todos, ¿alguien puede hacer un programa de C# que tenga una etiqueta inalcanzable dirigida por un goto accesible?" y verá quién en la fiesta ha leído la especificación de alcance y quién no.

+0

Agregaría errores: en tiempo de ejecución, sistema operativo, controladores, hardware, etc. que causaron BSOD o PC cuelga. –

+0

@EricLippert Si se produce una excepción de OutmentMemory en try block, creo que finalmente no se ejecutará. ¿Estoy en lo correcto al asumir eso? Por favor hagamelo saber. – Sandeep

+3

Así que la moraleja de la historia es: nunca invite a Eric Lippert a sus fiestas;) – Tergiver

4

Éstos son algunos ejemplos:

Environment.FailFast()

 try 
     { 
      Console.WriteLine("Try"); 
      Environment.FailFast("Test Fail"); 

     } 
     catch (Exception) 
     { 
      Console.WriteLine("catch"); 
     } 
     finally 
     { 
      Console.WriteLine("finally"); 
     } 

La salida es única "Prueba"

Stackoverflow

 try 
     { 
      Console.WriteLine("Try"); 
      Rec(); 
     } 
     catch (Exception) 
     { 
      Console.WriteLine("catch"); 
     } 
     finally 
     { 
      Console.WriteLine("finally"); 
     } 

¿Dónde está Rec:

private static void Rec() 
    { 
     Rec(); 
    } 

La salida sólo es "probar" y el proceso termina debido a StackOverflow.

excepción unhanded

 try 
     { 
      Console.WriteLine("Try"); 
      throw new Exception(); 
     } 
     finally 
     { 
      Console.WriteLine("finally"); 
     } 
Cuestiones relacionadas