获取类型参数不能从接受2类型args的函数中推断出错误

时间:2016-07-14 15:13:22

标签: c# exception

好的,我需要能够传入匿名方法和异常类型来进行检查。这是我现在正在尝试的一个剥离版本

public T MyMethod<T,E>(Func<T> action, E ExceptionType, int param2, int param3 = 3) where E : Exception
{
    try
    {
    //Some code here
    }
    catch(Exception ex)
    {
        if(ex.GetType() == typeof(ExceptionType))
        {
         //Do something
        }
        else
        {
          //Do something else
        }
    }
}

我正试图像这样调用这个方法

Retry(()=>OtherMethod("input"),typeof(Exception),33,9);

我一直得到同样的错误。 “无法从用法中推断出方法X的类型参数。请尝试明确指定类型参数”

我们的想法是检查MyMethod中抛出的异常是否与作为第二个参数传入的异常类型匹配,并根据它是否执行操作来执行操作。我不能只对代码进行硬编码,因为这将在库中使用,并且要检查的异常类型并不总是相同。

我可以改变什么来完成我正在尝试的东西?

编辑: 我也试过这样调用这个方法..

Retry(()=OtherMethod(),new Exception(),10,10)

但我得到同样的问题。

2 个答案:

答案 0 :(得分:2)

表达式typeof(Exception)的计算结果为TypeType不符合扩展Exception所需类型的条件。

该方法期望您传递某种异常的实例,而不是作为异常的Type对象。

如果要传递类型本身,请不要尝试推断泛型参数 - 将异常显式指定为泛型类型参数。如果要传递Type,请编写接受方法。

答案 1 :(得分:1)

Servy的回答是正确的。关于如何解决问题的一些想法:

第一个选项:采取类型:

public T MyMethod<T>(Func<T> action, Type exceptionType)
{
    ...
    catch(Exception ex)
    {
        if(ex.GetType() == exceptionType)

第二个选项:采用类型参数:

public T MyMethod<T, E>(Func<T> action)
  where E : Exception 
{
    ...
    catch(Exception ex)
    {
        if(ex.GetType() == typeof(E))

此解决方案存在一个问题:没有依据可以推断出类型参数E,因此调用者不能使用类型推断。

第三种选择:

public T MyMethod<T>(Func<T> action, Exception example)
{
    ...
    catch(Exception ex)
    {
        if(ex.GetType() == example.GetType())

呸。传入一个对象只是为了让你可以提取它的类型很奇怪。

所有解决方案都存在比较问题:

if(ex.GetType() == exceptionType)
if(ex.GetType() == typeof(E))
if(ex.GetType() == example.GetType())

这是有问题的;假设异常类型是AnimalException,而ex是GiraffeException类型,它派生自AnimalException。这些测试将失败,因为类型不是相等,并且这是相等检查。如果您采用这种方法,请考虑类型的完全匹配是否是您真正想要的。

  

我希望能够传入一个Type,但只限于从Exception继承的类型

哦,好吧,你为什么不这么说?

public T MyMethod<T>(Func<T> action, Type exceptionType)
{
    if (!typeof(Exception).IsAssignableFrom(exceptionType))
        throw new ArgumentException("exceptionType must represent a type derived from or equal to Exception");

容易腻。不要试图捕获类型系统中的所有内容。违反此规则的呼叫者将快速发现并解决问题。