2012-02-15 33 views
49

¿Hay situaciones en las que sea apropiado utilizar un bloque try-finally sin un bloque catch?Utilice un bloque 'try-finally' sin un bloque 'catch'

+0

En MSDN, consulte [try-finally (Referencia C#)] (https://msdn.microsoft.com/en-us/library/zwc8s4fz%28v=vs.140%29.aspx). Tenga en cuenta que el artículo se refiere al uso combinado de 'try' y' finally' como la declaración ** ** try-finally ** * *. – DavidRR

Respuesta

80

Lo utilizará para asegurarse de que se realicen algunas acciones después del contenido try o de una excepción, pero cuando no desee consumir esa excepción.

Para que quede claro, esto no oculta las excepciones. El bloque finally se ejecuta antes de que la excepción se propague por la pila de llamadas.

También lo usaría inadvertidamente cuando use la palabra clave using, porque esto se compila en un try-finally (no es una conversión exacta, pero por razones de argumento está lo suficientemente cerca).

try 
{ 
    TrySomeCodeThatMightException(); 
} 
finally 
{ 
    CleanupEvenOnFailure(); 
} 

código que se ejecuta en finally no se garantiza la ejecución, sin embargo, el caso en el que no se garantiza es bastante borde - no puedo ni siquiera recuerdo. Todo lo que recuerdo es que, si estás en ese caso, es muy probable que no ejecutar el finally no sea tu mayor problema :-) así que básicamente no te preocupes.

Actualización de Tobias:finally no se ejecutará si el proceso se cancela.

actualización de arroz:Conditions when finally does not execute in a .net try..finally block

El ejemplo más frecuente es posible que vea es disponer de una conexión de base de datos o recursos externos, incluso si el código falla:

using (var conn = new SqlConnection("")) // Ignore the fact we likely use ORM ;-) 
{ 
    // Do stuff. 
} 

compila en algo como :

SqlConnection conn; 

try 
{ 
    conn = new SqlConnection(""); 
    // Do stuff. 
} 
finally 
{ 
    if (conn != null) 
     conn.Dispose(); 
} 
+2

+1 para el ejemplo de código. –

+0

¿Hay alguna buena razón para hacer esto? ¿Es una excepción ocultar prácticas no muy malas? – AnthonyBlake

+11

@AnthonyBlake La excepción no está oculta. Si se produce una excepción, ejecutará finalmente y luego propagará la excepción a la pila de llamadas. –

1

Necesita un bloque finally, cuando no importa qué excepciones (si las hay) se capturan o incluso si no se captura ninguna, aún desea ejecutar algún código antes de que salga el bloque. Por ejemplo, es posible que desee cerrar un archivo abierto.

Ver también try-finally

1

try/finally: cuando no se quiere manejar las excepciones, pero quiere asegurarse de alguna acción (s) se produzca o no una excepción es lanzada por el código de llamada.

5

using es equivalente a try-finally. Solo usará try-finally cuando desee hacer una limpieza dentro de finally y no le importa la excepción.

El mejor enfoque habrá

try 
{ 
    using(resource) 
    { 
     //Do something here 
    } 
}catch(Exception) 
{ 
    //Handle Error 
} 

Si lo hace, incluso limpiar llamado por using falla, su código no fallará.

Hay algunas condiciones cuando finally no se ejecutarán.

  • Si hay StackOverflowException o ExecutingEngineException.
  • El proceso se elimina de una fuente externa.

Espero que esto responda a su duda.

2

Si tiene, por ejemplo, un recurso no administrado que crea y usa en el bloque try, puede usar el bloque finally para asegurarse de liberar ese recurso. El bloque finally siempre se ejecutará a pesar de lo que suceda (por ejemplo, excepciones) en el bloque try.

E.g. la cerradura (x) declaración es realmente:

System.Threading.Monitor.Enter(x); 
try { ... } 
finally 
{ 
    System.Threading.Monitor.Exit(x); 
} 

El bloque finally siempre se llamará para asegurar el bloqueo exclusivo se libera.

0

No sé nada de C#, pero parece que cualquier cosa que pudieras hacer con una prueba, finalmente, podrías hacer más elegantemente con un using statement. C++ ni siquiera tiene un finalmente como a result of its RAII.

2

Buena Explicación mediante código:

void MyMethod1() 
{ 
    try 
    { 
     MyMethod2(); 
     MyMethod3(); 
    } 
    catch(Exception e) 
    { 
     //do something with the exception 
    } 
} 


void MyMethod2() 
{ 
    try 
    { 
     //perform actions that need cleaning up 
    } 
    finally 
    { 
     //clean up 
    } 
} 


void MyMethod3() 
{ 
    //do something 
} 

Si bien MyMethod2 o MyMethod3 genera una excepción, será capturado por MyMethod1. Sin embargo, el código en MyMethod2 necesita ejecutar un código de limpieza, p. cerrar una conexión de base de datos, antes de que la excepción se pase a MyMethod1.

http://forums.asp.net/t/1092267.aspx?Try+without+Catch+but+with+finally+doesn+t+throw+error+Why+no+syntax+error+

+0

Un ejemplo de esta "limpieza" podría ser saveLogFile(), que a menudo quiero poner al final de un programa pase lo que pase. – Vincent

0

Aquí es un caso de uso que siempre (uhm ..) utilizo:

int? x; //note the nullable type here! 
try 
{ 
    x = int.Parse(someString); 
} 
catch { } //don't care, let it just be null 
1

Aquí es una situación en la que es posible que desee utilizar finalmente probar: cuando normalmente se utiliza un uso declaración, pero no puede porque está llamando a un método por reflexión.

Esto no funcionará

using (objMsg = Activator.CreateInstance(TypeAssist.GetTypeFromTypeName("omApp.MessagingBO"))) 
{ 

} 

en lugar de utilizar

  object objMsg = null; 
      try 
      { 
       objMsg 
        = Activator.CreateInstance(TypeAssist.GetTypeFromTypeName("myAssembly.objBO")); 

       strResponse = (string)objMsg.GetType().InvokeMember("MyMethod", BindingFlags.Public 
         | BindingFlags.Instance | BindingFlags.InvokeMethod, null, objMsg, 
         new object[] { vxmlRequest.OuterXml }); 
      }    
      finally 
      { 
       if (objMsg!=null) 
        ((IDisposable)objMsg).Dispose(); 
      } 
0

1. Podemos utilizar el bloque try sin capturas pero debe utilizar el catch/finally, cualquiera de ellos. 2. No podemos usar solo try block.

Cuestiones relacionadas