为什么调用这个重写方法?

db4*_*b42 3 c# generics overriding interface

public interface ITimeable     {}
public class TimedDoor : ITimeable  {}

public static class Timer
{
    public static void Add(ITimeable obj)
    {
       Console.Write("Add with parameter - ITimeable"); 
    }

    public static void Add(TimedDoor obj)
    {
       Console.Write("Add with parameter - TimedDoor"); 
    }
}

public class BaseClient<T> where T : ITimeable
{
    public T TimedDoorObject;
    public virtual void Init()
    {
        Timer.Add(TimedDoorObject);
    }
}

public class Client : BaseClient<TimedDoor>
{
    public Client()
    {
        TimedDoorObject = new TimedDoor();
    }

    public override void Init()
    {
        Timer.Add(TimedDoorObject);
    }
}
Run Code Online (Sandbox Code Playgroud)

在此Client.Init()返回"Add with parameter - TimedDoor"

但是如果Client没有覆盖Init(),

public class Client : BaseClient<TimedDoor>
{
    public Client()
    {
        TimedDoor = new TimedDoor();
    }
}
Run Code Online (Sandbox Code Playgroud)

在这里,Client.Init()返回"Add with parameter - ITimeable"

这是怎么回事?TimedDoorObject两种情况下在运行时都是相同的.

Sco*_*ain 8

如果我们添加一些显式的强制转换来表示T在该点Timer.Add(TimedDoorObject)被调用的内容,那么它会更明显地发生什么.

public class BaseClient<T> where T : ITimeable
{
    public T TimedDoorObject;
    public virtual void Init()
    {
        Timer.Add((ITimeable)TimedDoorObject);
    }
}

public class Client : BaseClient<TimedDoor>
{
    public Client()
    {
        TimedDoorObject = new TimedDoor();
    }

    public override void Init()
    {
        Timer.Add((TimedDoor)TimedDoorObject);
    }
}
Run Code Online (Sandbox Code Playgroud)

因此,当它被编译时,BaseClient它知道是T某种ITimeable对象,因此它能够链接到的最佳超载是void Add(ITimeable obj)版本.相比之下,在编译时Client知道T代表一个TimedDoor所以它使用void Add(TimedDoor obj)函数,因为它是一个更好的匹配void Add(ITimeable obj).