Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to catch all variants of a generic exception in C#

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.

like image 950
SBFrancies Avatar asked Nov 27 '19 15:11

SBFrancies


People also ask

Is there a generic exception catching mechanism in C++?

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 (...) { // ... }

How to handle exceptions in C++?

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.

How do I get the type of a catch exception?

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.

Is there a way to see the exception variable thrown in C++?

} 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.


Video Answer


2 Answers

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.

like image 111
Eliahu Aaron Avatar answered Oct 08 '22 19:10

Eliahu Aaron


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<>))
like image 7
Holger Avatar answered Oct 08 '22 18:10

Holger