带有约束泛型参数的奇怪方法重载解析:始终调用基类arg的重载

时间:2016-09-21 10:13:46

标签: c# generics overload-resolution

我有一些 - 可能真的很愚蠢 - 关于重载决策的问题。 假设有一个受约束的通用方法Greet接受类型person的参数T,它必须从Person派生。然后,此Greet方法在另一个类中调用一些非泛型方法,并将person作为参数传递。这种非泛型方法有几个重载 - 对于基类和派生类。为什么总是调用基类的重载?

示例:

public static class Test 
{
  public static void Greet() 
  {
    new SomeClass().Greet(new Person()); // Hi, I am a Person
    new SomeClass().Greet(new Manager()); // Hi, I am a Person -- Why?
  }
}
public class SomeClass 
{    
   public void Greet<T>(T person) where T : Person 
   {
     new Greeter().SayHi(person);
   }
}
public class Person { /* some props and methods */ }
public class Manager : Person { /* some props and methods */ }
public class Greeter 
{  
   public SayHi(Person person) { Console.WriteLine("Hi, I am a person"); }
   public SayHi(Manager person) { Console.WriteLine("Hi, I am a manager"); }
}

但是,只有SayHi接受一个Person总是被调用。为什么?

1 个答案:

答案 0 :(得分:3)

编译器必须为

的调用执行重载解析
 new Greeter().SayHi(person);

此时,person的类型只是T所有它知道T可以隐式转换为Person 。因此,Greeter中唯一适用的方法是SayHi(Person)

重要的是要理解这种情况发生在编译时,一次 - 对于用于T的每个类型参数,它不会在执行时单独发生。