如何在C#中捕获通用异常的所有变体

SBF*_*ies 13 c# generics exception

我想捕获一个通用异常类的所有变体,并且我想知道是否有一种方法可以在没有多个catch块的情况下进行。例如说我有一个异常类:

public class MyException<T> : Exception
{
    public string MyProperty { get; }

    public MyException(T prop) : base(prop.ToString())
    {
        MyProperty = prop?.ToString();
    }
}
Run Code Online (Sandbox Code Playgroud)

和两个派生类:

public class MyDerivedStringException : MyException<string>
{
    public MyDerivedStringException(string prop) : base(prop)
    {

    }
}

public class MyDerivedIntException : MyException<int>
{
    public MyDerivedIntException(int prop) : base(prop)
    {

    }
}
Run Code Online (Sandbox Code Playgroud)

有没有一种方法可以同时捕获MyDerivedStringExceptionMyDerivedIntException捕获一个捕获块。

我已经试过了:

try
{
   ...
}

catch(Exception e) when (e is MyDerivedStringException || e is MyDerivedIntException)
{
}
Run Code Online (Sandbox Code Playgroud)

但是它不是很干净,意味着我无法使用MyProperty

我对问题的一般解决方案感兴趣,但是在我的情况下,通用异常是在第三方库中定义的,如下所述,该库为问题增加了一些其他约束。

Eli*_*ron 10

使MyException<T>实现接口并按接口类型检查异常。

接口:

public interface IMyException
{
    string MyProperty { get; }
}
Run Code Online (Sandbox Code Playgroud)

实现该接口的泛型类:

public class MyException<T> : Exception, IMyException
{
    public string MyProperty { get; }

    public MyException(T prop)
    {
        MyProperty = prop?.ToString();
    }
}
Run Code Online (Sandbox Code Playgroud)

派生类:

public class MyDerivedStringException : MyException<string>
{
    public MyDerivedStringException(string prop) : base(prop)
    {

    }
}

public class MyDerivedIntException : MyException<int>
{
    public MyDerivedIntException(int prop) : base(prop)
    {

    }
}
Run Code Online (Sandbox Code Playgroud)

用法:

try
{
    // ...
}
catch (Exception e) when (e is IMyException)
{
    // ...
}
Run Code Online (Sandbox Code Playgroud)

通过创建从该基类继承ExceptionMyException<T>从该基类派生的基类,可以做到这一点。

  • 我不确定这里是否值得使用一个接口-只需在Exception和MyException &lt;T&gt;之间使用非通用基类就可以了。 (3认同)

Hol*_*ger 9

如果您Type是从泛型派生的,则测试为:

Type = typeof(something);
t.GetGenericTypeDefinition()==typeof(MyException<>);
Run Code Online (Sandbox Code Playgroud)

但这仅适用于派生类型本身,例如MyException<int>MyException<string>

如果您还有其他衍生产品MyDerivedStringException,则必须进行以下测试:

ex.GetType.BaseType.GetGenericTypeDefinition()==typeof(MyException<>);
Run Code Online (Sandbox Code Playgroud)

因此,这适用于任何现有的泛型,但是您需要知道此测试的继承级别,或遍历所有基本类型。

因此,您可以这样做:

catch(Exception ex) when (ex.GetType.BaseType.GetGenericTypeDefinition()==typeof(MyException<>))
Run Code Online (Sandbox Code Playgroud)