具有约束泛型参数的奇怪方法重载决议:总是调用基数 class arg 的重载

strange method overload resolution with constrained generic arguments: overload with base class arg always called

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

示例:

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

但是,总是只调用接受 Person 的 SayHi。为什么?

编译器必须为

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

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

重要的是要了解这种情况发生在编译时,一次 - 对于用于 T.

的每个类型参数,它不会在执行时单独发生