C#编译器如何区分抽象方法的具体子类impl和抽象基类中的重载?

时间:2015-09-24 07:37:15

标签: c# .net generics compiler-construction overloading

如果您有基类

public abstract class AbsHashtableish<TKey, TValue>
{
    public abstract TKey ConvertToKey(string key);
    public abstract bool KeyExists(TKey key);

    public virtual bool KeyExists(string key)
    {
         Console.WriteLine("In Base");
         return KeyExists(ConvertToKey(key));
    }
}

和一个概念类

public class ConcreteHashtableish: AbsHashtableish<string, Dinosaur>
{
    ...

    public override string ConvertToKey(string key)
    {
         return key;
    }

    public override bool KeyExists(string key)
    {
         Console.WriteLine("In Sub");
         return _list.Contains(key);
    }
}

和客户A

AbsHashtableish<string, Dinosaur> concreteA = new ConcreteHashtableish<string, Dinosaur>();

和客户B

ConcreteHashtableish<string, Dinosaur> concreteB = new ConcreteHashtableish<string, Dinosaur>();

用于确定上面显示的代码是否足以编译的规则(如果可能,背后的原因)是什么规则,如果是这样的话:

  1. KeyExistsconcreteA之间调用concreteB之间是否存在差异?
  2. 假设我们可以某种方式进入基类方法KeyExists(string key),我们能够摆脱它吗?
  3. 对于问题#2,我的意思是,如果编译器能够以某种方式编译此代码,它是否通过有效地从客户端隐藏基本方法来实现 - 因为如果达到该代码,则会导致无限循环?

1 个答案:

答案 0 :(得分:2)

KeyExistsconvreteA上拨打concreteB最终都是一样的。

Common Language Runtime (CLR)知道调用实际类型的方法(使用Virtual Method Table)。这是Polymorphism的重点。它允许您将具体实现称为抽象实现,但实际调用的方法是具体类型。

在您给出的特定示例中,您不能在派生类之外使用KeyExists的基类实现,只是因为您无法创建抽象类的实例。如果它不抽象,你可以创建:

AbsHashtableish<string, Dinosaur> baseA = new AbsHashtableish<string, Dinosaur>();

AbsHashtableish.KeyExists将被调用。

编辑:(感谢Oliver注意到)

您始终可以从派生类内部调用基类实现。在这种情况下,您可以致电:

base.KeyExists(key)