2010-04-28 13 views
10

He adquirido el hábito de usar una declaración de catch general y manejo esas excepciones de manera general. ¿Es esta mala práctica? De ser así, ¿cómo puedo saber qué excepciones específicas podrían arrojarse y cuáles puedo detectar?En C#, ¿cómo sé qué excepciones tomar?

+0

Ojalá hubiera un 'modo anal' para VS2008/10 que lo forzaría a manejar todas las excepciones. –

+0

@Hamish: podría intentar hacer una extensión. Sin embargo, las excepciones sin marcar fueron una elección de diseño muy deliberada, basada en las lecciones aprendidas de Java. –

+0

@Greg D, ¿cómo podría implementar esto? –

Respuesta

17
  1. Sí, excepto en un par de casos muy específicos, es una mala práctica. El único caso común en el que puedo pensar es que capturar todas las excepciones no es una mala idea cuando estás registrando un mensaje o un seguimiento de la pila justo antes de que la aplicación esté a punto de desmoronarse (o, tal vez, estás registrando y re-lanzamiento).

  2. Captura solo las excepciones que sabes que puedes manejar. Ni mas ni menos. Si no sabe que puede arrojarse una excepción desde un método, no lo va a manejar correctamente de todos modos, así que no lo atrape. Los métodos y las bibliotecas son responsables de documentar las excepciones que debería poder manejar. Además, no detecta excepciones que indiquen una falla lógica, como NullReferenceException y ArgumentException. Estos indican un error genuino en su software que debe corregir, no algo que debe manejar en tiempo de ejecución.

+4

En mi humos, los errores de lógica deberían ser atrapados también. Es mejor Fail and Log que explotar en una cara de usuarios/clientes. Esos errores no deberían aparecer, por supuesto, pero siempre lo hacen y a los clientes no les importa qué tipo de problema causó el colapso, solo recuerdan que entregó el software bloqueado. Estoy de acuerdo con la mayoría de lo que dijiste sin embargo. – dbemerlin

+5

@dbemerlin: los clientes odian el software que no funciona correctamente y no saben por qué. Siempre debe apagar su aplicación frente a excepciones no controladas. –

+0

@dbemerlin: estoy de acuerdo con usted desde el punto de vista de que "los clientes ven un error y eso es malo". Sin embargo, si las pruebas han cumplido su función, deberían encontrar muchos/la mayoría de esos errores lógicos y usted puede manejar los errores correctamente (como verificar que un objeto no sea nulo, o validar entradas antes de manejar un formulario, etc.) – JasCav

3

Los métodos que ejecuta en general muestran las excepciones que se pueden lanzar. A continuación, puede atrapar en consecuencia.

Si se trata de su propio código, generalmente puede ver lo que se arrojará, o utilizar las excepciones de las clases subyacentes como una guía sobre lo que necesitará capturar.

me recomiendan algunos enlaces:

+0

Creo que la pregunta está preguntando cómo saber qué van a arrojar las clases subyacentes? p.ej. Java tiene una cláusula 'throws', que documenta esto. .NET no. – spoulson

+0

@spoul - Mueva el mouse sobre la clase o el método que está utilizando, y se nota. O usa el explorador de objetos. –

+4

en mi humilde opinión que no es una manera confiable de resolverlo. Quiero decir, cuando se usan EF y objetos POCO generados, nada de esto está documentado. Usar Linq enturbia las aguas aún más. ¿Qué pasa cuando uso contenedores DI y IoC? Whoa, ¡MUCHAS cosas para considerar y apenas una gota en el balde está documentado en la forma que sugieres! – Jaxidian

0

Al utilizar métodos marco, se puede comprobar la documentación de MSDN. Cada descripción de método tiene una lista de excepciones potencialmente lanzadas.

Como ejemplo, consulte el párrafo Excepciones en la documentación File.Open().

Al utilizar su propio método, debe tener en cuenta las excepciones que puedan generar sus métodos.

+0

O en Visual Studio, simplemente coloque el cursor sobre el método y lea el comentario del documento, también enumera los tipos de excepción lanzados. –

2

La pregunta más importante es si necesita realizar el manejo de errores específicos en excepciones específicas. Si sólo tiene que detectar los errores que se producen, no hay nada malo con sólo hacer un bloque try/catch genérica:

try 
{ 
    // Some Code 
} 
catch 
{ 
} 

Sin embargo, si necesita hacer un manejo específico sobre ciertas excepciones, se pueden especificar varios bloques catch por un solo intento:

try 
{ 
    // Some Code 
} 
catch(ArgumentException argE) 
{ 
} 
catch(NullReferenceException nullE) 
{ 
} 
catch(Exception e) 
{ 
    // Everything else 
} 

Si no puede recuperarse de una excepción, no atrapen a ese nivel.

5

Sí, eso es una mala práctica. Regla de oro: "capte las excepciones a las que está en posición de responder, deje que las otras se vayan".

try { 
    File.Open(usersChosenFile, FileMode.Open); 
} catch(FileNotFoundException) { 
    // tell the user the file is gone, give them a chance to respond 
    // this is good 
} catch(UnauthorizedAccessException) { 
    // this is good too 
} catch(Exception) { 
    // what did you just catch? Who knows. What if its OutOfMemoryException? 
    // Do you really want to deal with that here? Let this one go by 
} 
1

OMI - no coger ninguna excepción a menos que se va a agregar valor a la misma y/o que pueden ser manejados sólo en ese método.

Tenga un controlador de excepción común que maneje todas las excepciones no manejadas.

HTH.

1

Como dijo Kyle, haga sus métodos de poca longitud, ponga a prueba/atrape solo en áreas pequeñas. Pase el mouse sobre los métodos a los que llama; debería obtener una lista de excepciones a continuación. Esto no detectará todas las excepciones enumeradas, pero las excepciones también pueden descubrirse empíricamente si imprime el tipo de excepción dentro de su catch (Exception e) { ... }. Lo que está buscando es e.GetType().FullName y e.StackTrace y e.Message y e.InnerException ... o un subconjunto de lo que enumeré.

0

La documentación a menudo describe qué excepciones podría arrojar un método y las condiciones bajo las cuales podría suceder. Este es especialmente el caso con la documentación de referencia de Microsoft para .NET Framework.

En mi opinión, las excepciones solo deben detectarse si tiene un buen motivo para atraparlas. Esto generalmente significa que capturarlos y manejarlos de manera genérica es innecesario. Las excepciones de registro (una actividad muy común en un manejador de excepciones) solo deberían ocurrir en la parte inferior de la pila de llamadas o siempre que no vuelva a lanzar la excepción (posiblemente envuelta), que debería ser rara. Si desea realizar alguna acción en cada cuadro de la pila de llamadas cuando se produce una excepción, consulte las técnicas de Programación Orientada a Aspectos (AOP).

0

Excepto en situaciones raras, generalmente pienso en atrapar bloques como un olor a código.

Evite que se produzcan excepciones comprobando las condiciones de antemano. Por ejemplo, si lee desde un archivo, use las clases en System.IO para verificar si el archivo existe, en lugar de usar un bloque catch para manejar la situación donde el archivo no existe.

Los bloques de captura no deben formar parte de la lógica de su aplicación.

0

Debe tener en cuenta las excepciones para las que puede desarrollar una estrategia razonable para tratar el problema. No tiene sentido capturar una excepción si no hay una alternativa razonable (intentarlo más tarde, utilizando una tecnología/técnica diferente para lograr el mismo objetivo general, informando al usuario que el objetivo no se puede alcanzar en la actualidad y qué pueden hacer para remediar la situación).

Excepción (indulto): vale la pena tener algo en el nivel superior (por ejemplo, Application.ThreadException o AppDOmain.UnhandledException) para intentar registrar esas excepciones que no ha manejado. Si el registro falla, estás condenado de todos modos.

Pero tragarse ciegamente todas las excepciones (especialmente en un nivel bajo) puede llevar a sesiones de depuración/diagnóstico muy frustrantes.

0

Debe tomar una decisión de diseño en cuanto a si realmente necesita detectar todas las excepciones en ese punto del código. Conozco dos condiciones en las que la captura de Exception tiene sentido:

  • Si usted no puede permitir una excepción a la burbuja y poner fin a su aplicación.
  • El código de llamada espera que su método/propiedad arroje una excepción porque es una transacción atómica. En ese caso, atrapa todas las excepciones y regresa de forma segura.

La desventaja de detectar todas las excepciones es enmascarar un mensaje de error potencialmente útil e ignorarlo, lo que causa efectos secundarios inesperados en la aplicación.

Cuestiones relacionadas