I would like to catch all variants of a generic exception class and I was wondering if there is a way to do it without multiple catch blocks. For example say I have an exception class:
public class MyException<T> : Exception
{
public string MyProperty { get; }
public MyException(T prop) : base(prop.ToString())
{
MyProperty = prop?.ToString();
}
}
and two derived classes:
public class MyDerivedStringException : MyException<string>
{
public MyDerivedStringException(string prop) : base(prop)
{
}
}
public class MyDerivedIntException : MyException<int>
{
public MyDerivedIntException(int prop) : base(prop)
{
}
}
is there a way of catching both MyDerivedStringException
and MyDerivedIntException
in one catch block.
I have tried this:
try
{
...
}
catch(Exception e) when (e is MyDerivedStringException || e is MyDerivedIntException)
{
}
but it is not very clean and means I do not have access to MyProperty
.
I am interested in a general solution to the problem but in my case the generic Exception is defined in a third party library which as pointed out below adds some additional constraints to the problem.
A generic exception catching mechanism would prove extremely useful. Same as How to build a C++ Dll wrapper that catches all exceptions? Note that most crashes are not caused by exceptions in C++. You can catch all exceptions, but that won't prevent many crashes. try { // ... } catch (...) { // ... }
Exception handling is used to handle the exceptions. We can use try catch block to protect the code. Catch block is used to catch all types of exception. The keyword “catch” is used to catch exceptions.
catch (MyException ex) class, as it expects a type. Your best bet would be to create a base class or interface, catch it and get the type from there. There is already an answer on so here on how to get the type and do this.
} Note that the ... inside the catch is a real ellipsis, ie. three dots. However, because C++ exceptions are not necessarily subclasses of a base Exception class, there isn't any way to actually see the exception variable that is thrown when using this construct.
Make MyException<T>
implement an interface and check for an exception by the interface type.
Interface:
public interface IMyException
{
string MyProperty { get; }
}
Generic class implementing the interface:
public class MyException<T> : Exception, IMyException
{
public string MyProperty { get; }
public MyException(T prop)
{
MyProperty = prop?.ToString();
}
}
Derived classes:
public class MyDerivedStringException : MyException<string>
{
public MyDerivedStringException(string prop) : base(prop)
{
}
}
public class MyDerivedIntException : MyException<int>
{
public MyDerivedIntException(int prop) : base(prop)
{
}
}
Usage:
try
{
// ...
}
catch (Exception e) when (e is IMyException)
{
// ...
}
The same can be done by creating a base class that inherits from Exception
and than making MyException<T>
derive from that base class.
The test if your Type
is derived from a generic is:
Type = typeof(something);
t.GetGenericTypeDefinition()==typeof(MyException<>);
But this is true only for derived types itself, like MyException<int>
or MyException<string>
.
If you have further derivatives like MyDerivedStringException
you had to test on:
ex.GetType.BaseType.GetGenericTypeDefinition()==typeof(MyException<>);
So this works for any existing generic, but you need to know the level of inheritance for this test, or loop through all the base types.
So you could do this:
catch(Exception ex) when (ex.GetType.BaseType.GetGenericTypeDefinition()==typeof(MyException<>))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With