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:恐怕你提到了问题中提供的句子的最后一部分,但那一部分与非虚拟方法有关。谢谢你的回答。好像我错过了一顿午餐,我的大脑停止了:)