两个简单的C#继承方法导致不同的输出

时间:2016-05-31 15:02:56

标签: c# inheritance

以下代码给出了不同的输出。任何人都可以解释原因吗?

代码显示如下。结果集显示在它下面。 我已经在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

2 个答案:

答案 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");
        }
    }