Me gustaría capturar todas las variantes de una clase de excepción genérica y me preguntaba si hay una manera de hacerlo sin múltiples bloques de captura. Por ejemplo, digamos que tengo una clase de excepción:
public class MyException<T> : Exception
{
public string MyProperty { get; }
public MyException(T prop) : base(prop.ToString())
{
MyProperty = prop?.ToString();
}
}
y dos clases derivadas:
public class MyDerivedStringException : MyException<string>
{
public MyDerivedStringException(string prop) : base(prop)
{
}
}
public class MyDerivedIntException : MyException<int>
{
public MyDerivedIntException(int prop) : base(prop)
{
}
}
¿Hay alguna manera de atrapar a ambos MyDerivedStringExceptiony MyDerivedIntExceptionen un bloque de captura?
He intentado esto:
try
{
...
}
catch(Exception e) when (e is MyDerivedStringException || e is MyDerivedIntException)
{
}
pero no está muy limpio y significa que no tengo acceso MyProperty.
Estoy interesado en una solución general al problema, pero en mi caso la excepción genérica se define en una biblioteca de terceros que, como se señala a continuación, agrega algunas restricciones adicionales al problema.

ExceptionyMyException<T>estaría bien.La prueba si su
Typederiva de un genérico es:Pero esto es cierto solo para los tipos derivados en sí, like
MyException<int>oMyException<string>.Si tiene más derivados como los
MyDerivedStringExceptionque tuvo que probar:Entonces, esto funciona para cualquier genérico existente, pero necesita conocer el nivel de herencia para esta prueba, o recorrer todos los tipos base.
Entonces podrías hacer esto:
fuente
Esta implementación encajona y desempaqueta si T: Value es Valuetype ... pero con respecto a la utilización puede controlar las implicaciones de rendimiento con la cantidad de veces que intenta encajonar / desempaquetar.
Lógica
fuente
Desafortunadamente, no puedes atrapar con el
catch(MyException ex)clase, como se espera un tipo.Su mejor opción sería crear una clase base o interfaz, capturarla y obtener el tipo desde allí.
Ya existe una respuesta sobre lo que aquí sobre la manera de obtener el tipo y hacer esto.
fuente
esta implementación abstrae el delegado de manejo para el tipo de excepción fuera del contexto del T / C ... Esto puede ser un poco demasiado aventurero, pero lo bueno de esto es que puede inyectar diferentes manejadores dependiendo del alcance de la reutilización y el contexto de utilización.
lógica de registro
fuente