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

7

我在检查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)
    {
    }
}

假设有一堆派生类。我需要做的是,在处理异常时能够以相同的方式管理所有派生类。
类似于:
try{
    // code that raise the exception
}
catch (Exception e) {
   // some code here
   switch(e) {
       case DomainException:
            // do something
            break;
       default:
            //other code here
            break;
   }
}

然而,因为DomainException至少需要一个泛型参数,所以它会引发错误。

enter image description here

我尝试使用objectdynamic,但类型不匹配。

enter image description here

有任何线索吗?


同样的问题是catch(DomainException e)需要一个泛型类型参数,而dynamicobject不匹配。我不想为每个派生类都写一个catch或者case,我想使用基类。 - Rumpelstinsk
2个回答

8
很遗憾,对于您的问题,在.NET中泛型并不是这样工作的。泛型类型参数不会被擦除,因此A<T>不是A<object>(这当然会违反类型安全性!)。
如果您可以更改DomainException<T>的定义,最好的解决方案是添加一个中间非泛型类型。
class DomainException: Exception
{
  public readonly DomainExceptionCodes Code;
}

class DomainException<T>: DomainException
{
  public T Metadata;
}

然后您只需捕获非泛型异常以获取代码,而只需要泛型变量来访问元数据(这意味着您已经知道要在那里期望什么类型)。

如果您不能更改异常定义,不幸的是您唯一的选择是使用反射。以下类似的代码应该可以工作:

try
{
  ...
}
catch (Exception ex) 
  when (
        ex.GetType().IsGenericType 
        && ex.GetType().GetGenericTypeDefinition() == typeof(DomainException<>)
      )
{
  ...
}

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


1

正如这个Stack Overflow问题所述,你不能一次性捕获所有类型的异常。下面的代码(摘自其他问题)应该可以满足您的需求。

// ...

catch (FaultException ex)
{
    Type exceptionType = ex.GetType();

    if (exceptionType.IsGenericType)
    {
        // Find the type of the generic parameter
        Type genericType = ex.GetType().GetGenericArguments().FirstOrDefault();

        if (genericType != null)
        {
            // TODO: Handle the generic type.
        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接