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

本文关键字:类型参数 函数 错误 不能 获取 | 更新日期: 2023-09-27 17:56:54

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

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 个类型参数的函数推断错误

表达式

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

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

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

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。这些测试将失败,因为类型不相等,这是一个相等性检查。如果采用此方法,请考虑类型是否完全匹配是否是您真正想要的。

我希望能够传入一个类型,但将其限制为仅继承自异常的类型

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

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");

简单易行。不要尝试捕获类型系统中的所有内容。违反此规则的呼叫者将很快发现它并解决问题。