2009-02-02 24 views
30

Al escribir una aplicación C# cuya prioridad n. ° 1 es nunca fallar, ¿con qué frecuencia debería usar un bloque try-catch?¿Con qué frecuencia debo usar try and catch in C#?

¿Puedo encapsular todas las instrucciones en un método en los bloques try-catch?

public void SomeMethod() 
{ 
    try 
    { 
     // entire contents of the function 
     // library calls 
     // function calls 
     // variable initialization .. etc 
    } 
    catch (Exception e) 
    { 
     // recover 
    } 
} 

¿Cuáles son las desventajas de envolver todo en los bloques try-catch?

Respuesta

30

El único inconveniente es cuando se produce una excepción. No hay sobrecarga para envolver el código, excepto cuando ocurren excepciones.

Además, no desea utilizar try/catch para controlar el flujo. Considere esto (código incorrecto):

try { 

    FileStream fs = File.Open("somefile.txt", FileMode.Open); 

} catch (Exception ex) { 
    MessageBox.Show("The file does not exist. Please select another file"); 
} 

Obtendrá más rendimiento de algo como File.Exists. tales como:

if(!File.Exists("somefile.txt")) 
    MessageBox.Show("The file does not exist.") 

EDIT: conocer la MSDN direct quote:

encontrar y diseñar distancia código de excepción pesado puede resultar en una victoria Potencia decente . Tenga en cuenta que esto no tiene nada que ver con los bloques try/catch : solo incurre en el costo cuando se produce la excepción real. Usted puede usar tantos bloques try/catch como que desee. Usar excepciones gratuitamente es donde pierde rendimiento. Por ejemplo, debe mantenerse alejado de cosas como usar excepciones para el flujo de control.

+2

Bueno, hay una sobrecarga * mínima *. Algunos, pero muy, muy pequeño. –

+1

Lo malo es que el compilador JIT no puede alinear funciones que contienen construcciones de manejo de excepciones –

+17

Es posible que el archivo deje de existir en el intervalo entre la comprobación e intente abrirlo. * Necesitas * el bloque try-catch para asegurarte de que no se cuelga. –

1

Hay una sobrecarga de rendimiento para los bloques try, si lo haces, toda tu función funcionará más lenta de lo contrario. catch (Exception e) también es una mala idea, si detecta que desea hacer algo útil con lo que capturó, y si detecta todas las excepciones, es imposible saber qué debe hacer.

+0

+1 para explicar la desventaja de atrapar (Excepción e). – jason

+1

A menos que esté haciendo algo como iniciar sesión y volver a lanzarlo. –

8

En realidad, muy raramente utilizo un bloque catch excepto para fines de registro. finally es mucho más común para mí. La mayoría de las veces, lock o using hacen todo lo que puedo hacer de manera útil (y de hecho, eso también es finally).

Eric Lippert tiene un blog entry on exceptions que puede ser útil.

+1

(o para manejadores de UI de nivel superior, por supuesto) –

1

Puede hacer esto, aunque casi en cualquier entorno en el que se está ejecutando, hay un controlador de excepción global donde puede detectar y manejar incluso errores desconocidos.

Para aplicaciones web, está el Global.asax, para un programa de consola, simplemente envolver su principal() en un try/catch, para los servicios, hay AppDomain.CurrentDomain.UnhandledException, etc.

Usted debe envolver secciones donde puede predecir cuál es la excepción en bloques más específicos, pero los manejadores de excepciones globales deberían simplificar en gran medida su código y ayudarlo.

-1

Debe usarlos cada vez que un fragmento de código pueda arrojar una excepción.

Tienes que tener cuidado, capturar excepciones generales nunca es una buena idea. Debes decidir qué capa quieres manejar.

Cuanto más profundo se encuentre, más ganas tendrá de captar excpección muy específica e ir más general. En una base de datos, capture la SqlException. A medida que avanzas más en la pila, obtienes más excepciones para finalmente atrapar la excepción general en la parte superior.

De esta manera puede manejar cada excepción caso por caso. Una excepción general que no sabrá qué hacer.

+2

* Cada * línea de código puede arrojar una excepción. OutOfMemoryException, ThreadAbortException, etc ... Y solo debería atraparlo si puede hacer algo útil. La mayoría de las veces, no puedes. –

4

Generalmente IMO es mejor poner trozos más pequeños que están fuera de tu control en una captura de prueba. Si usted dice:

try 
{ 
    //anything that could possibly go wrong 
    //This kind of thing is only good for Logging IMO and could be done in 
    //Global.asax 
} 

¿Cómo es posible saber qué hacer en su método de captura causa podría ser cualquier cosa ...

Es mucho mejor ir:

try 
{ 
    //divide user imputs 
} 
catch(DivideByZeroException) 
{ 
    // tell user bad inputs ect.... 
} 
catch (Exception e) 
{ 
    //If you choose to throw the exception you should 
    //*********************** 
    throw; 
    //VS 
    throw ex; //Throw ex will restart the stack trace 
    // recover 
} 
finally 
{ 
    //Clean up resources and continue 
} 

En qué finalmente es ejecutado

+1

Mejor aún no captar la excepción y simplemente verificar de antemano si existe – jlembke

3

la clave de esta pregunta es la siguiente línea:

// recover 

Para poder recuperarse, debe saber qué y cómo recuperarlo. Y eso es suponiendo que es posible recuperarlo, lo que con frecuencia no sucede.

Solo debe usar la parte catch de try/catch/finally para tragar una excepción cuando sepa cómo manejar la excepción, cuando sepa cómo recuperarse de ella y cuando esté seguro de que puede hacerlo sin abandonar la aplicación un estado inconsistente o inválido.

Si puede hacer esto para todas las excepciones posibles en todas las llamadas a métodos en su aplicación, continúe adelante; de ​​lo contrario, podría necesitar volver a pensar su prioridad # 1 (a veces fallar rápido es una mejor opción que tratar de mantener la aplicación está activa cuando algo ha salido mal, y después tiene una falla de depuración mucho más difícil).

0

Nuestra aplicación actual tiene un mandato similar: nunca falle. Siempre retrocede graciosamente. Para hacer esto, debes asegurarte de que cada línea de código esté encerrada en un bloque try-catch o solo sea llamada por código en el que puedan saltar sus excepciones.

Además, para proteger contra las excepciones no detectadas, adjuntamos UnhandledExceptionEventHandler a AppDomain.CurrentDomain.

+1

No he votado a favor, pero su declaración "debe asegurarse de que cada línea de código esté incluida en una prueba". catch block ... "comienza con el pie izquierdo. Es la segunda parte de la declaración que debe asegurarse de que siempre haya un controlador de excepciones en sentido ascendente. – jdigital

+0

Esto parece un mal diseño. De todo lo que he leído, debe usar try-catch para manejar el entorno, situaciones que dependen de los recursos de la red (o servidor) o que están fuera de su control. Por lo tanto, voy a votar abajo. – ConfusedDeer

2

Solo debe capturar y detener la excepción sin volver a lanzarla si puede manejarla de manera significativa. De lo contrario, es un error y debería propagarse.

Supongo que cuando dicen "esta aplicación nunca se cuelga", existe un requisito implícito de que se comporte correctamente. Solo detener excepciones que se manejan de manera significativa satisface el requisito de comportamiento correcto.

Normalmente, una aplicación tendrá un único bloque catch de nivel superior para capturar y registrar excepciones no controladas. Esto debe ocurrir con poca frecuencia (y tal vez su requisito puede interpretarse en el sentido de que esto no debería suceder en absoluto). Si detecta y detiene excepciones en cualquier otro lugar de su código, corre el riesgo de no descubrir estos problemas. Si detecta el registro y se detiene en muchas otras partes de su código, tiene una aplicación mal construida desde la perspectiva de la separación de las preocupaciones.

23

Este es un gran tema. here empezar por algún excelente discusión de las mejores prácticas de manejo de excepciones y estar preparados para una guerra religiosa ...

Code Analysis Team Blog

Martin Fowler - Fail Fast

MSDN on Exception Handling

Checked vs Unchecked Exceptions

Mi propia opinión es que en su mayor parte usa mucho "try/finally", pero "catch" muy poco. El problema es que si intenta atrapar y manejar Excepciones en las instancias incorrectas, puede poner inadvertidamente su aplicación en mal estado. Como regla general, use dev y test para saber dónde necesita manejar una excepción. Esos serán lugares que no puedes verificar. es decir, no debería necesitar manejar nullreference o filenotfound porque puede verificarlos proactivamente. Solo pueden ocurrir excepciones, pero no puede hacer nada al respecto. Más allá de eso, por el bien del estado de tus datos, déjalo colapsar.

Si está tragando excepciones, generalmente significa que no comprende su programa o por qué está recibiendo una excepción. Alcanzando System.Exception es el niño del cartel de código olores ... catch

+2

exactamente, si su aplicación arroja una excepción, intente y descubra por qué se lanza esa excepción en primer lugar, luego coloque las comprobaciones (es decir, si el archivo existe) para evitarlas. –

+0

Si la "prioridad n. ° 1 es nunca bloquearse", esto es bueno en teoría, pero no cumple con los requisitos. Estoy seguro de que le gustaría discutir sobre los requisitos, pero sospecho que el OP no tiene esto como una opción (si lo hiciera, ya le habría explicado esto a su cliente ;-) – jdigital

+0

@jdigital - de acuerdo. Ese es un buen punto. Su pregunta especifica "never crash" – jlembke

-3

intento en C#:

try{ 

} 
catch (NullReferenceException en) 
{ 

} 
+3

-1: Nunca capture 'NullReferenceException' - _fix_ it en su lugar. –

-1
public void functionName 
{ 
    try 
    { 
    //your codes 
    //sometimes 'return' shows exceptions 
    } 
    catch(Exception e) 
    { 
    messagebox.show(e.Tostring()); //to know what is the exception 
    } 
    finally 
    { 
    } 
} 
1

trato de evitar try catch bloques general. Prefiero usar loops para obligar al usuario a obedecer las reglas de una aplicación. Por ejemplo, si un usuario sólo debe introducir un int que es igual o inferior a un int x que haría uso:

if (input > x) 
{ 
    Console.WriteLine("Invalid input. Please enter a number that is equal to or less than x."); 
{...} 
} 

en lugar de utilizar:

catch (IndexOutOfRangeException) 
{ 
     //error message here 
} 

Desde mi propia experiencia personal, le resulta más fácil escribir, ya que puede evitar encapsular el código en un bloque de prueba (código de protección).

Por supuesto, siempre habrá ocasiones en las que el uso de try catch sea inevitable; solo me gustaría trabajar en ello cuando sea posible.