2016-09-21 30 views
1

我有一些 - 可能真的很愚蠢 - 关于重载分辨率的问题。 假设有一个受限制的通用方法Greet接受T类型的参数person,该参数必须来自Person。这Greet方法然后在另一个类中调用一些非泛型方法,将person作为参数传递。该非泛型方法有几个重载 - 对于基类和派生类。为什么总是调用基类的重载?奇怪的方法重载分辨率与约束泛型参数:基类arg总是调用

实施例:

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的接受人总是调用。为什么?

+1

在使用'dynamic'之外,重载分辨率是在*编译时*而不是* runtime *执行的。它必须选择一种方法来编译呼叫。 –

回答

3

编译器必须执行重载解析为

new Greeter().SayHi(person); 

呼叫在这一点上,中person类型只是T,并且它知道一切T隐式转换为Person。因此,Greeter中唯一适用的方法是SayHi(Person)

重要的是要明白,这是发生在编译时,一次 - 它不会在执行时分别发生用于T的每个类型参数。

+0

是否存在一种实现相同意图的非丑陋模式(没有丑陋的'if'语句链来检查参数的类型? – AunAun

+1

@AunAun:使'Greet'成为'Person'中的虚拟方法而不是'Greeter '?或者使用'动态'... –