我有一个名为Item
的类,它充当抽象类,但未定义为一个类。该类具有MaxPerStack
属性:
public class Item
{
public short MaxPerStack
{
get
{
return this.Data.MaxPerStack;
}
}
}
我还有一个名为Equip
的类,它派生自Item
类,并且还有一个名为MaxPerStack
的属性,声明为new
:
public class Equip : Item
{
public new short MaxPerStack
{
get
{
return 1;
}
}
}
我有以下方法Add
,它使用MaxPerStack
的{{1}}属性:
item
当我这样做时:
public void Add(Item item)
{
Console.WriteLine("Stack: {0}.", item.MaxPerStack);
}
它转到Add(new Equip());
的{{1}}属性而不是MaxPerStack
属性。
为什么会这样?
答案 0 :(得分:5)
因为您没有将Item.MaxPerStack
标记为virtual
,并且您没有将Equip.MaxPerStack
标记为override
。你需要这两个来获得你期望的行为。
通过隐式将基本类型的方法标记为sealed
并明确将派生类型标记为new
,您可以防止虚拟调度,这是用于实现的确切机制确保调用基类型的方法将执行与对象的实际运行时类型关联的实现,而不是将方法静态绑定到编译时中的实现对象的类型。
答案 1 :(得分:1)
此处的问题是,您的Equip
类会替换MaxPerStack
类中定义的Item
属性。
public class Equip : Item
{
public new short MaxPerStack
{
get
{
return 1;
}
}
}
MSDN告诉您:
如果派生类中的方法前面带有new关键字,则该方法被定义为独立于基类中的方法。
...
使用new关键字告诉编译器您的定义隐藏了基类中包含的定义。这是默认行为。
这也适用于属性。这告诉您Equip
将拥有它自己的,不相关的MaxPerStack
版本。因此,当您致电Item.MaxPerStack
时,您正在Item
课程中访问该媒体资源,而不是Equip
课程。无论您传入的Item
实际上是Equip
类。
要解决此问题,您可以将MaxPerStack
属性设为虚拟,然后在Equip
类中覆盖它。
public class Item
{
public virtual short MaxPerStack
{
get
{
return this.Data.MaxPerStack;
}
}
}
public class Equip : Item
{
public override short MaxPerStack
{
get
{
return 1;
}
}
}
现在,当您向Equip
提供Add(Item)
作为参数时,Add
方法将访问MaxPerStack
类的Equip
属性。
MSDN告诉你:
如果派生类中的方法前面带有override关键字,派生类的对象将调用该方法而不是基类方法。