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

C# 基类或派生类是运行时类型?,c#,.net,clr,C#,.net,Clr,我一直在阅读有关virtual方法的文档: 在虚拟方法调用中,的实例的运行时类型 调用发生的位置决定了实际的方法 要调用的实现。在非虚拟方法调用中 实例的编译时类型是决定因素。在里面 使用参数列表调用名为N的方法时的精确术语 在编译时类型为C、运行时类型为R的实例上的 (其中R是C或从C派生的类),调用是 处理如下…: 然而,我注意到上面有些粗体字。假设我们有这样一个代码: class Planet{ public string Name; public float Size; p

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

在虚拟方法调用中,的实例的运行时类型 调用发生的位置决定了实际的方法 要调用的实现。在非虚拟方法调用中 实例的编译时类型是决定因素。在里面 使用参数列表调用名为N的方法时的精确术语 在编译时类型为C、运行时类型为R的实例上的 (其中R是C或从C派生的类),调用是 处理如下…:

然而,我注意到上面有些粗体字。假设我们有这样一个代码:

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
的类呢。基类类型不是在运行时解析的吗?

要调用的正确方法将在运行时解析,方法是从中选取。因此,如果您添加到
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
将调用地球的方法

在我的示例中,编译时类型是
Planet
,但运行时类型是
Earth

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

要调用的正确方法将在运行时通过从中选取来解析。因此,如果您添加到
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
将调用地球的方法

在我的示例中,编译时类型是
Planet
,但运行时类型是
Earth


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

您错了-编译时类型(C)是
Earth
,运行时类型(R)也是
Earth
。您指出的规范部分在这里并不真正相关

相关的是,具体而言:

将构造用于方法调用的候选方法集。 从与M关联的一组方法开始,发现 通过先前的成员查找(第7.3节),集合将减少到 适用于参数列表A的方法

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

如果代码为:

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

(特别是如果地球为
SpinPlanet
定义了一个覆盖),因为编译类型(变量的类型)将是
Planet
,但运行时类型将是
Earth
,您错了-编译时类型(C)是
Earth
,运行时类型(R)也是
Earth
。您指出的规范部分在这里并不真正相关

相关的是,具体而言:

将构造用于方法调用的候选方法集。 从与M关联的一组方法开始,发现 通过先前的成员查找(第7.3节),集合将减少到 适用于参数列表A的方法

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

如果代码为:

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

(特别是如果地球为
SpinPlanet
)定义了一个覆盖,因为编译类型(变量的类型)将是
Planet
,但运行时类型将是
Earth

我认为您错误地标记了C/R-它们都是
Earth
。您的场景是
行星世界=新地球()在粗体语句前面写着:“实例的编译时类型为C,运行时类型为R”。在“C world=new R()”中,R可以是C,也可以是从C派生的类型。C是“world”的编译时类型,R是它的运行时类型。我想你没有正确地标记C/R——它们都是
Earth
。您的场景是
行星世界=新地球()在粗体语句前显示:“编译时类型为C、运行时类型为R的实例”。在“C world=new R()”中,R可以是C或从C派生的类型。C是“world”的编译时类型,R是其运行时类型。我在问粗体语句是否为真?@Braveyard:当然是真的!“在虚拟方法调用中,发生该调用的实例的运行时类型决定了要调用的实际方法实现”。发生了什么。@Braveyard:恐怕你提到了问题中提供的句子的最后一部分,但那一部分与非虚拟方法有关。谢谢你的回答。好像我错过了一顿午餐,我的大脑停止了:)我在问这个大胆的说法是不是真的?@Braveyard:当然是真的!“在虚拟方法调用中,发生该调用的实例的运行时类型决定了要调用的实际方法实现”。发生了什么。@Braveyard:恐怕你提到了问题中提供的句子的最后一部分,但那一部分与非虚拟方法有关。谢谢你的回答。好像我错过了一顿午餐,我的大脑停止了:)