2010-10-27 23 views
17

Esto es un poco abstracto, pero ¿hay alguna manera posible de lanzar una excepción y hacer que entre en varios bloques catch? Por ejemplo, si coincide con una excepción específica seguida de una excepción no específica.¿Puedo ejecutar varios bloques de captura?

catch(Arithmetic exception) 
{ 
    //do stuff 
} 
catch(Exception exception) 
{ 
    //do stuff 
} 

Respuesta

30

Es perfectamente aceptable tener múltiples bloques de captura de diferentes tipos. Sin embargo, el comportamiento es que el primer bloque candidato maneja la excepción.

No entrará AMBOS bloques de captura. El primer bloque de catch que coincida con el tipo de excepción manejará esa excepción específica, y ninguna otra, incluso si se vuelve a lanzar en el controlador. Cualquier subsecuente será omitido una vez que una excepción entre en un bloque catch.

Con el fin de tener una excepción capturada en ambos bloques, que se necesita para cualquiera de los bloques de nido, así:

try 
{ 
    try 
    { 
     // Do something that throws ArithmeticException 
    } 
    catch(ArithmeticException arithException) 
    { 
     // This handles the thrown exception.... 

     throw; // Rethrow so the outer handler sees it too 
    } 
} 
catch (Exception e) 
{ 
    // This gets hit as well, now, since the "inner" block rethrew the exception 
} 

Como alternativa, puede filtrar en un gestor de excepciones genérico basado en el tipo específico de excepción.

+2

El anidamiento funciona bien para las jerarquías simples de un nivel, pero puede tener problemas si tiene un código compartido que debe ejecutarse para varios casos de excepciones diferentes. Esto no es un desacuerdo con el enfoque, sino una observación de que no siempre es apropiado. – tvanfosson

+0

@tvanfosson: Sí, por eso también agregué la opción de filtrado. Tu opción también es muy buena. –

18

No. No es posible ejecutar el código en ambos bloques catch para una única excepción.

Probablemente refactorice el código en el bloque de excepción genérico en algo que pueda invocarse desde cualquiera de los dos.

try 
{ 
    // blah blah blah 
{ 
catch(Arithmetic ae) 
{ 
    HandleArithmeticException(ae); 
    HandleGenericException(ae); 
} 
catch(Exception e) 
{ 
    HandleGenericException(e); 
} 
1

No puede haber más de un bloque de excepción que maneje la misma excepción. Pero lo que puede hacer es detectar la excepción general, entonces tratar de echar a la más específica, como esto:

catch (Exception exception) 
{ 
    var aex = exception as ArithmeticException 
    if (aex != null) 
    { 
     // do stuff specific to this exception type 
    } 
    // then do general stuff 
} 
0

Esto se conoce como el filtrado de excepción y no es compatible con C# (me dijeron es posible en VB.NET).

Una alternativa sería detectar la excepción general y luego verificar el tipo de excepción en el bloque catch y hacer cualquier procesamiento específico sobre eso antes de continuar con el resto del bloque.

1

Al igual que otros, la excepción se detectará en el bloque catch más específico.

Esto me trae una frustración aunque con manejo de excepciones. Me gustaría que podría hacer algo como

catch (ArgumentNullExcpetion, ArugmentOutOfRangeException ex) 
{ 

} 

En lugar de tener que hacer

catch (ArgumentNullExcpetion e) 
{ 
} 
catch (ArugmentOutOfRangeException outOfRange) 
{ 
} 

entiendo el razonamiento en contra de este que es probable que hacer cosas diferentes para diferentes excepciones, pero a veces me quiere combinarlos.

+1

No se derivan ambos de ArgumentException; si realmente desea hacer lo mismo para ambos, simplemente tome ArgumentException. Si desea capturar solo las excepciones secundarias, entonces deberá filtrar (y volver a lanzar) ArgumentException utilizando la lógica condicional. Tu punto general es bueno, pero este no es el mejor ejemplo. Tal vez algo como ValidationException (error de modelo) y SqlException (violación de restricción) donde no están en la misma jerarquía es un mejor ejemplo. – tvanfosson

+1

No creo que esté 100% en lo cierto cuando dice "la excepción será atrapada por el bloque catch más específico". Eso también depende del orden. Entonces, si tiene una captura, primero todo siempre caerá en eso, incluso si tiene más específicos después de – jon

+0

tvanfosson. Buena atrapada. Acabo de hacer este ejemplo sobre la marcha. Tiene razón, podría atrapar la excepción general para padres en este caso. Pero sí me gustaría una forma de atrapar múltiples tipos de excepciones no relacionadas en un bloque catch –

2

Si estaba usando VB.NET, podría abstraer su controlador de errores en la excepción aritmética en una función o método que siempre devuelve falso.

Posteriormente, se podría escribir algo como:

Catch ex as Arithmetic When HandleArithmetic() 
Catch ex as Exception 

End Try 

No es que yo estaría a favor de tal uso, aunque he visto que recomienda para propósitos de registro antes. No creo que haya un equivalente de C#.

Cuestiones relacionadas