Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/299.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C#编译器如何区分抽象方法的具体子类impl和抽象基中的重载?_C#_.net_Generics_Compiler Construction_Overloading - Fatal编程技术网

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

C#编译器如何区分抽象方法的具体子类impl和抽象基中的重载?,c#,.net,generics,compiler-construction,overloading,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

如果你有一个基类

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));
    }
}
公共抽象类AbsHashtableish
{
公共抽象TKey CONVERTOKEY(字符串键);
公共抽象布尔键存在(TKey);
公共虚拟布尔键存在(字符串键)
{
控制台。写入线(“在底部”);
返回键存在(ConvertToKey(键));
}
}
还有一节混凝土课

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);
    }
}
public类ConcreteHashtableish:AbsHashtableish
{
...
公共重写字符串转换键(字符串键)
{
返回键;
}
公共覆盖布尔键存在(字符串键)
{
控制台。写入线(“子系统”);
返回_list.Contains(键);
}
}
客户A

AbsHashtableish<string, Dinosaur> concreteA = new ConcreteHashtableish<string, Dinosaur>();
AbsHashtableish concreteA=new ConcreteHashtableish();
和客户B

ConcreteHashtableish<string, Dinosaur> concreteB = new ConcreteHashtableish<string, Dinosaur>();
ConcreteHashtableish concreteB=new ConcreteHashtableish();
确定上面显示的代码是否足以编译的规则是什么(如果可能,还有背后的推理),如果可以:

  • concreteA
    上调用
    KeyExists
    concreteB
    之间是否有区别
  • 假设我们可以以某种方式进入基类方法
    keyissets(string-key)
    ,那么我们能从中解脱出来吗

  • 对于问题#2,我的意思是,如果编译器能够以某种方式编译这段代码,它是否通过有效地向客户机隐藏基本方法来做到这一点——因为如果达到了这段代码,这将导致无限循环?

    convreteA
    concrete上调用
    KeyExists
    最终是相同的

    公共语言运行库(CLR)
    知道调用实际类型上的方法(使用)。这就是我的全部观点。它允许您将具体实现称为抽象实现,但实际调用的方法属于具体类型

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

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

    在具体类中,您可以通过使用
    base.KeyExists(key)
    @AndroidJoker调用基实现。因此,可以公平地说,编译器向CLR编写的指令是“调用KeyExists的这个或那个特定实现”,或者改为“Call KeyExists,我知道到时候你会知道的。”@tacos\u tacos\u tacos:Down在IL代码中只显示“Call KeyExists”“然后运行时将查看该类的vtable。有一个指向应该调用的方法的指针,如果派生类重写了它,它将指向具体实现,否则指向基实现。当运行时加载类型时,会创建vtable内容。但我不是专家,所以如果我弄错了什么,任何人都可以纠正我。
    base.KeyExists(key)