基类或派生类是运行时类型?

时间:2012-04-18 17:48:10

标签: c# .net clr

我一直在阅读有关virtual方法的文档:

  

在虚方法调用中,实例的运行时类型   调用发生的位置决定了实际的方法   要调用的实现。在非虚方法调用中,   编译时类型的实例是决定因素。在   精确术语,当使用参数列表调用名为N的方法时   A在具有编译时类型C和运行时类型R的实例上   (其中R是C或从C 派生的类),调用是   处理如下......:   http://msdn.microsoft.com/en-us/library/aa645767(v=vs.71).aspx

然而,我注意到上面有些大胆的东西。假设我们有这样的代码:

class Planet{
  public string Name;
  public float Size;
  public virtual void SpinPlanet(){
     Console.WriteLine("Hoooraaay!!!");
  }
}

class Earth : Planet{

}

我的代码中的某处:

Earth world = new Earth();
world.SpinPlanet();

在这种情况下:

  • N SpinPlanet()
  • C Earth
  • R Planet

那么R如何成为编译时类型C的派生类。是否在运行时解析基类类型?

2 个答案:

答案 0 :(得分:3)

你错了 - 编译时类型(C)是Earth 运行时类型(R)也是 {{1} }。您指出的规范部分在这里并不重要。

相关的是http://msdn.microsoft.com/en-us/library/aa691356(v=vs.71).aspx,具体是:

  

构造方法调用的候选方法集。   从找到的与M相关联的方法集开始   通过先前的成员查找(第7.3节),该集合被简化为那些   适用于参数列表A的方法。

Earth的唯一候选实现恰好位于SpinPlanet的基类中,而不是在派生类中。

如果代码是:

,则您引用的规范部分将适用
Earth

(特别是如果Earth定义了Planet world = new Earth(); world.SpinPlanet(); 的覆盖),因为编译类型(变量的类型)将是SpinPlanet,但运行时类型将是Planet。< / p>

答案 1 :(得分:2)

调用的正确方法将在运行时通过从Virtual Methods Table中选择来解析。因此,如果您添加到Earth

class Earth : Planet{
   public override void SpinPlanet(){
     Console.WriteLine("Hoooraaay Earth!!!");
  }
}

这样的代码

Planet world = new Earth();
world.SpinPlanet(); //even if declared type Planet, 
                    // the real type remain Earth, so its  method will be called

将调用Earth's方法。

my 示例中,编译时类型为Planet,但运行时类型为Earth

你的示例中,编译时和运行时类型是相同的Earth