通用方法解决方案

时间:2014-08-18 16:52:12

标签: c# generics overload-resolution

请考虑以下代码:

public class Tests
{
    public void Test()
    {
        Assert.AreEqual("Int", DoSomething(1));
    }

    public static string DoSomething<T>(T value)
    {
        return "Generic";
    }

    public static string DoSomething(int value)
    {
        return "Int";
    }
}

正如预期的那样,将调用非泛型的DoSomething方法。现在考虑以下修改:

public class Tests
{
    public void Test()
    {
        Assert.AreEqual("Int", DoSomething(1));
    }

    public static string DoSomething<T>(T value)
    {
        return "Generic";
    }

    public static string DoSomething<T>(int value)
    {
        return "Int";
    }
}

我唯一改变的是将T类型参数添加到第二个重载,从而使其成为通用的。请注意,不使用type参数。

该修改导致调用第一个DoSomething方法。为什么?编译器具有选择第二种方法所需的所有信息。

您能否解释为什么,甚至更好地指出解释此行为的C#规范部分?

2 个答案:

答案 0 :(得分:10)

在您的调用中,您没有指定类型参数 - 因此编译器必须推断T的类型。它不能为您的第二个方法执行此操作,因为声明的参数中从未提及type参数。因此,该重载不适用,并被忽略。

如果您为通话指定了类型参数,例如

中的任何一个
DoSomething<int>(1)
DoSomething<object>(1)
DoSomething<string>(1)

...然后在所有情况下都会调用第二个重载。

在构建候选方法集时,从C#5规范的第7.6.5.1节(方法调用):

  
      
  • 如果F是通用的且M没有类型参数列表,则F是以下情况的候选者:   
        
    • 类型推断(第7.5.2节)成功,推断出调用的类型参数列表,
    •   
    • 一旦推断的类型参数替换相应的方法类型参数,F的参数列表中的所有构造类型都满足其约束(§4.4.4),并且F的参数列表适用于A(§) 7.5.3.1)。
    •   
  •   

由于类型推断没有成功,第二种方法不在候选集中,所以当我们实现真正的重载解析时,该集只有一个方法(第一个)。

答案 1 :(得分:-1)

编译器无法确定调用DoSomething(1)中的模式类型,但如果指定[int],则会选择另一种方法。