以下代码给出了不同的输出。任何人都可以解释原因吗?
代码显示如下。结果集显示在它下面。
我已经在Enterprise VS 2015,Update 2上编译了代码。
我在Win7上运行它。
请注意我在两个示例中都使用了阴影(隐藏)。这个问题并不涉及阴影与重写的使用。问题是"为什么阴影导致两个不同的输出?"
以下是编译和运行的代码,并为调用对象的两种不同方法提供了不同的结果:
using System;
namespace InheritanceApplication
{
internal class FooBarParent
{
public void Display()
{
Console.WriteLine("FooBarParent::Display");
}
}
internal class FooBarSon : FooBarParent
{
public new void Display()
{
Console.WriteLine("FooBarSon::Display");
}
}
internal class FooBarDaughter : FooBarParent
{
public new void Display()
{
Console.WriteLine("FooBarDaughter::Display");
}
}
internal class Example
{
public static void Main()
{
GoodBar();
FooBar();
}
public static void GoodBar()
{
Console.WriteLine("Example::Goodbar ...");
var fooBarParent = new FooBarParent();
fooBarParent.Display();
var fooBarSon = new FooBarSon();
fooBarSon.Display();
var fooBarDaughter = new FooBarDaughter();
fooBarDaughter.Display();
}
public static void FooBar()
{
Console.WriteLine();
Console.WriteLine("Example::Foobar ...");
var fooBarFamily = new FooBarParent();
fooBarFamily.Display();
fooBarFamily = new FooBarSon();
fooBarFamily.Display();
fooBarFamily = new FooBarDaughter();
fooBarFamily.Display();
}
}
}
以下是结果集:
Example::Goodbar ...
FooBarParent::Display
FooBarSon::Display
FooBarDaughter::Display
Example::Foobar ...
FooBarParent::Display
FooBarParent::Display
FooBarParent::Display
答案 0 :(得分:3)
执行此操作时:
var fooBarFamily = new FooBarParent();
您(隐式)声明fooBarFamily
属于FooBarParent
类型。
由于Display
方法不是虚拟的,因此没有虚拟调度。因此,您调用的方法仅由声明的类型的fooBarFamily
确定。
因此,在每次调用fooBarFamily.Display
时,无论实例的运行时类型是什么,都要调用FooBarParent.Display()
。
相反,当您为每个实例提供自己的var
时,类型将被推断为您正在创建的实例的类型:
var fooBarSon = new FooBarSon();
为您提供fooBarSon
类型FooBarSon
,因此您正在调用FooBarSon.Display()
;同样适用于fooBarDaughter
。
答案 1 :(得分:0)
您不应在继承方案public new void Display()
中使用new。
当您说new而不是override时,取消此方法的继承。
为了获得正确的行为,你应该写:
internal class FooBarParent
{
public virtual void Display()
{
Console.WriteLine("FooBarParent::Display");
}
}
internal class FooBarSon : FooBarParent
{
public override void Display()
{
Console.WriteLine("FooBarSon::Display");
}
}
internal class FooBarDaughter : FooBarParent
{
public override void Display()
{
Console.WriteLine("FooBarDaughter::Display");
}
}