2009-11-18 22 views
12

Duplicar posibles:
Catch multiple Exceptions at once?C# manejo de excepciones caída A través

¿Hay alguna forma en C# para lograr fácilmente la siguiente pseduo-código:

try 
{ 
... 
} 
catch (ExceptionTypeA, ExceptionTypeB, ExceptionTypeC as ex) 
{ 
... same code for all threw 
} 

O

try 
{ 
... 
} 
catch (ExceptionTypeA ex) 
catch (ExceptionTypeB ex) 
catch (ExceptionTypeC ex) 
{ 
... same code for all exceptions of A, B or C 
} 

Supongo que lo que estoy diciendo sería genial sería un fracaso en los tipos de excepción.

+3

¿Extraer el código común de una función no es una opción? –

+0

Vea también la solución aquí: http://stackoverflow.com/questions/136035/catch-multiple-exceptions-at-once –

+0

La forma C# 6: https://stackoverflow.com/a/22864936/96944 –

Respuesta

15

El problema con la sintaxis mencionada (con un ex) es: ¿qué propiedades/miembros debería tener ex? Diferentes tipos de excepciones no son necesariamente compatibles, a menos que haya herencia involucrada (en cuyo caso, tome el menos derivado que le interese).

La única opción actual es simplemente usar Exception ex (o similar) y verificar (is/as) dentro del controlador.

O; refactorizar el código común en un método que pueda ser utilizado por los tres?

+0

Es en realidad es una petición razonable, porque a veces realmente quieres atrapar 'Derived1' y' Derived2' pero no 'Derived3', por lo que no puedes simplemente capturar' Base', y sin embargo quieres hacer lo mismo para ambos. Estaba programado para Java 7 en algún momento, con sintaxis como 'catch (Derived1 | Derived2 ex)', y solo le daba miembros del tipo de base común más cercano, pero desde entonces lo han descartado para esta versión. Aún así, sería una adición interesante al sistema de tipos en general. –

+0

Quizás, pero va junto con el argumento de costo VS beneficio. ¿Qué tan difícil es simplemente crear un método para la lógica común? –

+1

Dependiendo de la cantidad de datos que utiliza del alcance que rodea 'try', el esfuerzo de crear dicho método puede ser desde momentáneo a moderado, y la legibilidad del código resultante desde moderadamente complejo hasta un desastre completo. –

4

Ajustar el código repetitivo en un método.

try 
{ 
... 
} 
catch (ExceptionTypeA ex) 
{ 
    DoSomething(); 
} 
catch (ExceptionTypeB ex) 
{ 
    DoSomething(); 
} 
catch (ExceptionTypeC ex) 
{ 
    DoSomething(); 
} 
catch (Exception ex) 
{ 
    DoTheDefaultSomething(); 
} 
+0

El problema aquí es el alcance de las variables a las que se puede acceder desde DoTheDefaultSomething. –

+0

@Nissan Fan: ¿Está sugiriendo que DoTheDefaultSomething() debería ser DoTheDefaultSomething (ex)? – Clark

+0

No, más variables con alcance en la porción Try ... Catch son que tienen un alcance para la función que contiene la porción Try ... Catch que estaría fuera del alcance en este escenario. –

1

Derivaría TypeA, B, C de una clase base común si esto es razonable. Y atrapa la excepción de la clase base.

4

Puede atrapar una excepción general y luego examinar el tipo, por ejemplo:

catch (Exception ex)    
    {     
     if (ex is ExceptionTypeA || 
      ex is ExceptionTypeB) 
      { 
       /* your code here */ 
      } 
     else 
      { 
       throw; 
      } 
    } 

Editar: en línea con otras respuestas estaría buscando para aclarar lo que está pasando tirando de un método - sino que las capturas individuales y un método común, probablemente introduciría un método para aclarar lo que está haciendo el contenido de la declaración if. Así que en lugar de

if (ex is ExceptionTypeA || ex is ExceptionTypeB) 

se había convertido en algo así como:

if (IsRecoverableByDoingWhatever(ex)) 

que creo que sería aclarar la intención más que sacar el código del controlador (aunque eso podría ser útil hacerlo también).

1

No es una manera limpia. Usted podría simplemente atrapar System.Exception y luego verificar el tipo en tiempo de ejecución, es decir.

try 
{ 
... 
} 
catch (System.Exception ex) 
{ 
    if (ex is ExceptionTypeA or ExceptionTypeB or ExceptionTypeC) 
    { 
     ... same code ... 
    } 
    else 
     throw; 
} 

... pero esto es bastante feo. Sería más agradable, como dijo João Angelo, tener bloques de captura separados para cada tipo de excepción, pero llama un método común en cada uno de ellos.

9

En resumen, no.No puedo pensar en dos tres alternativas:

captura cada excepción, y llamar a un método común:

try 
{ 
    // throw 
} 
catch (ExceptionTypeA ex) 
{ 
    HandleException(); 
} 
catch (ExceptionTypeB ex) 
{ 
    HandleException(); 
} 
catch (ExceptionTypeC ex) 
{ 
    HandleException(); 
} 

void HandleException() 
{ 
} 

O coger todo, y utilizar una sentencia if del tipo:

try 
{ 
    // throw 
} 
catch (Exception ex) 
{ 
    if (ex is ArgumentException || ex is NullReferenceException || ex is FooException) 
    { 
     // Handle 
    } 
    else 
    { 
     throw 
    } 
} 

EDITAR: O bien, podría hacer algo como esto:

List<Type> exceptionsToHandle = new List<Type>{ typeof(ArgumentException), typeof(NullReferenceException), typeof(FooException) }; 

try 
{ 
    // throw 
} 
catch (Exception ex) 
{ 
    if (exceptionsToHandle.Contains(ex.GetType())) 
    { 
     // Handle 
    } 
    else 
    { 
     throw 
    } 
} 
1

Si tiene acceso al código que define las excepciones personalizadas, una solución posible es:

Cree un tipo de excepción personalizado.

public abstract class CustomException : Exception 
{ 
     //Do some stuff here 
} 

luego hacer todas sus excepciones personalizadas se derivan de este tipo de base:

public class MyException1 : CustomException 
{ 
     // Do some stuff here 
} 

public class MyException2 : CustomException 
{ 
    // Do some stuff here 
} 

haya terminado. Entonces, todo lo que necesita en su código de cliente es atrapar la clase base de excepción personalizada.

try 
{ 
    //Do something that throws a custom exception 
} 
catch (CustomException ex) 
{ 
    // Do some shared behavior for all the custom exceptions 
} 
3

Si es necesario utilizar algunas variables del ámbito de try, utilizar una función anidada. Es decir, un delegado lambda o anónimo:

int x = ...; 
Action<Exception> handler = delegate(Exception ex) 
{ 
    // Same code for all exceptions of A, B or C. 
    // You can use variable x here too. 
};  

try 
{ 
... 
} 
catch (ExceptionTypeA ex) { handler(ex); } 
catch (ExceptionTypeB ex) { handler(ex); } 
catch (ExceptionTypeC ex) { handler(ex); }