2009-10-27 31 views
7

Estoy ejecutando un código a través de FxCop y actualmente estoy buscando eliminar todas las infracciones sin interrupción.Manejo de excepciones generales en C#

El código en sí tiene algunas instancias de bloques de prueba/captura que solo captan excepciones generales;

try 
{ 
    // Some code in here that could throw an exception 
} 
catch(Exception ex) 
{ 
    // Exception Thrown ... sort it out! 
} 

Ahora todos sabemos que esto es una mala práctica, pero pensé que sabía cómo hacerlo correctamente - pero FxCop tiene otras ideas!

Supongamos que el código en el bloque try podría arrojar una excepción IO, y solo una excepción IO. No debe haber nada malo en hacer esto:

try 
{ 
    // Code in here that can only throw an IOException 
} 
catch (System.IO.IOException ioExp) 
{ 
    // Handle the IO exception or throw it 
} 
catch (System.Exception ex) 
{ 
    // Catch otherwise unhandled exception 
} 

Pero FxCop no está de acuerdo conmigo ... Todavía banderas esto como una violación porque yo estoy poniendo System.Exception.

¿Es realmente una mala práctica o debería/puedo ignorar esta violación?

+1

Depende ... ¿qué estás haciendo en "// Capturar excepción no controlada"? – Heinzi

+0

La aplicación es capaz de enviar correos electrónicos a nuestro servicio de ayuda, que pasan al desarrollo, por lo que probablemente activemos uno de ellos con el seguimiento de la pila. – DilbertDave

+0

¿Está absolutamente seguro de que el bloque de código no puede arrojar una excepción OutOfMemoryException, por ejemplo, u otro error fatal ...? – SoftMemes

Respuesta

6

Estoy de acuerdo con FxCop y la mayoría de las otras respuestas aquí: no debe quedar atrapado System.Exception jamás, a menos que sea al más alto nivel en su aplicación para conectarse inesperados (y por lo tanto fatales) excepciones y luego bombardear la aplicación. Also check out this question that's basically about the same thing.

Algunas otras excepciones válidas podrían ser:

  • capturar excepciones por la única razón de Regeneración de uno más descriptivo.
  • Código de prueba de unidad que necesita algo más complejo que ExpectedExceptionAttribute.
  • En el código de biblioteca de fachada que solo existe para proteger a las personas que llaman de las complejidades de llamar a un servicio externo (web), aunque nunca falla realmente, sin importar qué tan grave sea el sistema externo.
+0

¿Qué sucede si desea iniciar sesión con la excepción de ciertos valores de los parámetros del método de nivel inferior que se produce? No se puede hacer desde el "nivel más alto en su aplicación". – Swanny

+0

@Swanny: ¿Qué pasa con Exception.Data para esto en el caso general? ¿O tipos de excepción personalizados con propiedades adicionales? No es un problema. Y también puede detectar una excepción en el nivel inferior en el que tiene acceso a esos datos, registrarla si es necesario y empaquetar la excepción en un tipo de excepción más descriptivo (personalizado) que arrojar. No es un problema, por lo tanto, ¿verdad? – peSHIr

+0

Aún debe completar la recopilación de datos, por lo que tiene que atrapar la excepción para hacerlo, por lo que tenemos otra excepción que no podemos hacer. Y aqui esta otro. Supongamos que estoy procesando un gran archivo por lotes de registros independientes y recibo una excepción inesperada procesando un registro. ¿Lanzo esta excepción inesperada al "nivel más alto"? No, lo registro y me muevo al siguiente registro, probablemente hasta que llegue al final del archivo o los máximos registros permitidos, lo que ocurra primero. – Swanny

4

Si está escribiendo library (framework), entonces FxCop es 100% correcto.

Capturas excepciones - ¿Qué significa? que sabes por qué arrojaron. ¿Estás seguro de que sabes todas las razones posibles?

Si escribe solo la aplicación, es posible que haya variaciones. Por ejemplo, si captura todas las excepciones no controladas para el registro.

+0

Estoy seguro de que nunca se pueden saber todos los motivos, pero mirando las llamadas al método dentro del bloque try Sé que el fragmento actual de código podría arrojar al menos 8 tipos de excepciones diferentes. – DilbertDave

+0

que debe manejarlos por separado. Una excepción puede ser porque el nombre del archivo no es válido, otro porque el disco tiene un error IO. Debe responder por separado, ya que conducirá la comunicación con sus usuarios. o simplemente ignore FxCop si le parece aburrido :-). –

+0

Pero si solo voy a 'devolver falso'; de cada bloque de captura parece bastante inútil. Estamos comenzando con herramientas de análisis de código como FxCop y necesitamos revisar su uso de ellas. – DilbertDave

2

¿Qué dice FxCopy sobre la infracción específica? Si solo desea registrar información sobre una excepción, vuelva a lanzarla, esto es perfectamente válido, aunque hay otras maneras en que esto podría hacerse. Si se vuelven a levantar él sin embargo, asegúrese de que sólo tiene que utilizar:

throw; 

y no

throw ex; 

Tal vez esa es la cuestión?

+1

Hay algunas instancias de esto pero que se marcan como una violación de RethrowToPreserveStackDetails. – DilbertDave

+0

Vaya, vaya FxCop. ¿Cuál era el nombre de la violación que estaba recibiendo al capturar System.Exception? – Swanny

+0

violación en cuestión es DoNotCatchGeneralExceptionTypes: http://msdn2.microsoft.com/library/ms182137(VS.90).aspx – DilbertDave

2

Si el código en el bloque solo debe arrojar una IOException, entonces ¿por qué quiere atrapar System.Exception también?

Luego, el grado de conformidad con las pautas FxCop que desea lograr es una elección suya. No vería nada malo en capturar cada excepción en el nivel más alto posible y registrar toda la información que pueda, por ejemplo.

2

Solo debe detectar las excepciones que puede hacer algo al respecto. De lo contrario, permita que la excepción se propague a la persona que llama o, por ejemplo, en una aplicación Gui, las excepciones deben ser manejadas por un controlador genérico catch all y luego registradas. Ver: UnhandledException Así que no te sorprendas a menos que tengas la intención de hacer algo con eso ... admitidamente eso podría simplemente estar registrando el error.

Editar También se fijan en Application.ThreadException

+0

Cierto, pero seguramente, a menos que detecte TODAS las excepciones en algún momento, llegará a la interfaz de usuario como una excepción no controlada. – DilbertDave

+0

@DilbertDave: que en lo que a mí respecta debería ser la única excepción a la regla de nunca atrapar 'System.Exception'. – peSHIr

+0

@DilbertDave ¿no es por eso que asigna un controlador al evento UnhandledException? –

3

Se supone que tragar excepciones que sabe cómo manejar. Capturar la excepción y no arrojarla (ya sea directamente o envuelto en una excepción específica) significa que conoce los detalles de la excepción en el contexto de la aplicación. Como Exception puede ser cualquier cosa, es poco probable que sepa cómo manejarla.

Si solo está registrando la excepción, no es gran cosa, simplemente conéctela y tírela a una capa externa para manipularla o atraparla.

+0

Excepto por supuesto, ¿qué hace la capa externa con la excepción si no la esperaba? – Swanny

+0

Normalmente, no hará mucho con él, pero un controlador de excepciones globales de última oportunidad puede atraparlo, proporcionar comentarios al usuario y evitar que la aplicación se cierre. No es la responsabilidad de una biblioteca de clases hacer esto, es la responsabilidad del anfitrión. –

+0

que suena como una manera perfectamente sana de manejar una excepción inesperada.Pero, ¿aceptarían que hay casos en que una biblioteca de clases no lanzaría la excepción inesperada, como el archivo por lotes de registros independientes que he mencionado más de una vez en esta página? – Swanny

4

gris área ...

En un mundo ideal vosotros todos los días cogería una excepción explícita, ya que, en teoría, esos son la única clase que puede hacer frente con sensatez - todo lo demás debe filtrarse a través de la parte superior a un cierto nivel entrenador de animales.

El problema es que no necesariamente vivimos en un mundo ideal y es posible que deseemos usar un controlador genérico para acumular información adicional sobre la excepción genérica (parámetros, etc.) en la excepción y/o realizar registros adicionales antes de aprobar la excepción respalda el árbol y, en cualquier caso, en el nivel apropiado, para organizar las cosas de forma tal que nuestros usuarios finales no vean excepciones en la interfaz de usuario. El contador de esto sería sugerir que cuando se producen nuevos errores a un nivel bajo (en lugar de llegar a su manejador de nivel de aplicación) luego se agrega un manejo específico de la excepción que puede hacer su captura por usted, pero puede haber problemas de implementación con esto. una solución donde se incluye un caso genérico en bits de código que, por cualquier razón, son un poco más propensos a las excepciones no controladas que a uno le pueden gustar.

Si fuera yo probablemente estaría considerando la bandera en una asamblea de base de montaje ...

P. S. Supongo que en ningún momento tiene un controlador que se traga la excepción y permite que la aplicación continúe.

+0

Espera. Solo captas las excepciones que esperas. Entonces, ¿quedan excepciones inesperadas para bloquear tu programa? Eso no es lo que yo llamaría una solución profesional. Observe el manejo de excepciones generales de WinForms que se introdujo para WinForms (1.1 o 2.0). Y si necesitaba procesar 1 millón de registros independientes en un archivo, prefiero atrapar la excepción inesperada, registrar el error en un registro junto con el número de registro y luego pasar al siguiente registro, posiblemente con un número de registro máximo malo permitido. – Swanny

+0

Erm, de manera más enfática * no * sugerí que las excepciones inesperadas deberían bloquear su programa. c.f. "gestor de nivel superior": el caso específico que usted plantea también es un punto muy bueno, por lo tanto, la observación adicional de que debe tratar la noción caso por caso. – Murph

+0

Lo sentimos, no leí el resto de su mensaje. Mi muy mal. – Swanny

5

Estoy de acuerdo con las otras respuestas que catch (Exception ex) está bien si bien

  1. sólo tiene que entrar y volver a lanzar la excepción o
  2. haces al más alto nivel (UI) de su aplicación.

Hay otra situación que viene a la mente en el que podría tener sentido: Al escribir código sin interacción (por ejemplo, algunos servicios del sistema), puede tener sentido perfecto para mantener el programa que se ejecuta si algunos (bienestar definida) la subtarea falla por la razón que sea. Por supuesto, se debe tener cuidado para asegurar que la razón del problema se registre y (tal vez) la tarea se intente de nuevo después de un tiempo.