¿Manejo de excepciones más elegante que varios bloques de captura?

Usando C #, ¿hay una mejor manera de manejar múltiples tipos de excepciones en lugar de un montón de bloques de captura desagradables?

¿Qué se considera la mejor práctica para este tipo de situación?

Por ejemplo:

try { // Many types of exceptions can be thrown } catch (CustomException ce) { ... } catch (AnotherCustomException ace) { ... } catch (Exception ex) { ... } 

En mi opinión, un montón de bloques de captura “feos” ES la mejor manera de manejar esa situación.

La razón por la que prefiero esto es que es muy explícito. Está indicando explícitamente qué excepciones desea controlar y cómo se deben manejar. Otras formas de tratar de combinar el manejo en formas más concisas pierden legibilidad en la mayoría de los casos.

Mi consejo sería seguir con esto y manejar las excepciones que desea manejar de forma explícita, cada una en su propio bloque catch.

Estoy de acuerdo con Reed: este es el mejor enfoque.

Yo agregaría estos comentarios:

Solo atrapa algo sobre lo que vas a hacer algo. Si no puede solucionar el problema, no tiene sentido capturar una excepción específica.

No exageres en el uso de bloques de captura. En muchos casos en los que no puede resolver la excepción, lo mejor es dejar que la excepción salte a un punto central (como Page_Error) y atraparla allí. Luego, registra la excepción y muestra un mensaje al usuario.

La única otra cosa que puedes hacer es emular los filtros de excepción de VB.NET:

 try { DoSomething(); } catch (Exception e) { if (!ex is CustomException && !ex is AnotherCustomException) { throw; } // handle } 

A veces esto es mejor, a veces no. Lo usaría principalmente si hubiera alguna lógica común que quisiera en el controlador, pero las excepciones no comparten un tipo base.

Desafortunadamente, C # no tiene filtros de excepción de usuario como VB.NET, por lo que está limitado a:

  1. Atrapando un ancestro común a todas las excepciones. Esto puede ser o no lo que desee, ya que puede haber otros tipos de excepciones descendientes que no desee capturar.
  2. Mover la lógica de manejo de excepciones a otro método y llamarla desde cada controlador.
  3. Repitiendo la lógica de excepción para cada controlador.
  4. Mover la lógica de manejo de excepciones a un lenguaje que admita filtros, como VB.NET.

Si necesitas escribir una gran cantidad de código como este, te sugiero que verifiques algún marco AOP . Yo personalmente uso PostSharp . Entonces podrías esconder todos los códigos de manejo de excepciones en aspectos.

Debería verificar el bloque de Gestión de excepciones de Enterprise Library. Permite un control mucho más fino de las excepciones a través de políticas (políticas de ajuste, políticas de propagación, políticas de reemplazo, políticas de registro, etc.) Puede usarlo para estandarizar la forma en que codifica un bloque de excepción y usa la configuración para manejar con precisión lo que sucede con un tipo particular de excepción.

¿De esta manera no es bueno?

Si desea manejar solo una excepción:

 try { // Many types of exceptions can be thrown } catch (TheExceptionIWantToHandle ex) { // handle it } catch (Exception ex) { // suppress all other exceptions } 

Si desea manejar todas las excepciones excepto una:

 try { // Many types of exceptions can be thrown } catch (TheExceptionIDoNotWantToHandle ex) { // suppress all other exceptions } catch (Exception ex) { // handle it } 

bueno, no bueno?

Captura solo lo que necesitas resolver específicamente y vete

 catch(Exception e) { } 

para todo lo demás (u omítalo y dé estas excepciones a la stack)