如何在 C# 中对泛型类型执行 switch 语句?

Rum*_*nsk 7 c# generics switch-statement

我在检查 switch 语句的正确类型时遇到了一些麻烦。我有这些课程延伸自Exception

public abstract class DomainException<T>: Exception
{
    public readonly DomainExceptionCodes Code;
    public readonly T Metadata;

    public DomainException(DomainExceptionCodes code, T metadata): base(message: code.GetEnumDescription())
    {
        Code = code;
        Metadata = metadata;
    }
}

public class EmptyFieldsException : DomainException<EmptyFieldsMetadata>
{
    public EmptyFieldsException(EmptyFieldsMetadata metadata) : base(code: DomainExceptionCodes.EmptyField, metadata)
    {
    }
}
Run Code Online (Sandbox Code Playgroud)

我们假设有一堆派生类。我需要做的是在处理异常时能够以相同的方式管理所有派生类。

就像是:

try{
    // code that raise the exception
}
catch (Exception e) {
   // some code here
   switch(e) {
       case DomainException:
            // do something
            break;
       default:
            //other code here
            break;
   }
}
Run Code Online (Sandbox Code Playgroud)

但是,由于DomainException泛型类型至少需要一个参数,因此会引发错误

在此输入图像描述

我尝试使用objectand dynamic,但类型不匹配

在此输入图像描述

有什么线索吗?

Lua*_*aan 8

不幸的是,对于您的问题,这不是泛型在 .NET 中的工作方式。泛型类型参数不会被删除,因此A<T>不会被删除 A<object>(这当然会违反类型安全!)。

如果您可以更改 的定义DomainException<T>,最好的解决方案是添加中间非泛型类型:

class DomainException: Exception
{
  public readonly DomainExceptionCodes Code;
}

class DomainException<T>: DomainException
{
  public T Metadata;
}
Run Code Online (Sandbox Code Playgroud)

然后,您可以捕获非通用异常来获取代码,并且只需要通用变体来访问元数据(这大概意味着您已经知道那里需要什么类型)。

如果您无法更改异常定义,不幸的是您唯一的办法就是使用反射。像这样的东西应该有效:

try
{
  ...
}
catch (Exception ex) 
  when (
        ex.GetType().IsGenericType 
        && ex.GetType().GetGenericTypeDefinition() == typeof(DomainException<>)
      )
{
  ...
}
Run Code Online (Sandbox Code Playgroud)

不幸的是,在这种情况下,即使要访问代码,您也需要使用反射。