【问题标题】:Two simple C# Inheritance methods result in different output [duplicate]两种简单的 C# 继承方法导致不同的输出 [重复]
【发布时间】:2016-05-31 15:02:56
【问题描述】:

以下代码给出不同的输出。谁能解释一下为什么?

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

【问题讨论】:

  • 你知道什么是virtual,你什么时候“”使用它?并且使用var 是模棱两可的
  • 看看这个SO Question
  • FooBar 中,fooBarFamily静态类型作为FooBarParent 的一个实例。因此,当您将其设置为 FooBarSon 的实例时,它不会改变。所以它仍然会调用FooBarParent.Display()
  • 我拒绝这是对 Ivan Stoev 在 C# 中阴影和覆盖之间的区别的重复问题? 5 个答案。
  • 请注意,我最好使用虚拟。但是,我不是在问“如何最好地编写代码”。我在问,为什么这段代码会给出不同的输出?

标签: c# inheritance


【解决方案1】:

当你这样做时:

var fooBarFamily = new FooBarParent();

您(隐式)声明 fooBarFamily 的类型为 FooBarParent

因为Display方法不是虚拟的,所以没有虚拟调度。所以你调用的方法只由fooBarFamilydeclared类型决定。

因此,在每次调用fooBarFamily.Display 时,无论实例的运行时类型是什么,您都在调用FooBarParent.Display()

相反,当您为每个实例赋予其自己的var 时,类型会被推断为您正在创建的实例的类型:

var fooBarSon = new FooBarSon();

为您提供FooBarSon 类型的fooBarSon,因此您调用的是FooBarSon.Display()fooBarDaughter 也是如此。

【讨论】:

    【解决方案2】:

    您不应该在继承场景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");
            }
        }
    

    【讨论】:

    • Msdn 说:“override 修饰符扩展了基类方法,而 new 修饰符隐藏了它”(msdn.microsoft.com/en-gb/library/ms173153.aspx)。如果他想隐藏原来的,他为什么不应该使用 new ?
    • 我认识到有更好的方法来编写上述代码。我不是在问“我如何获得我正在寻找的结果”。我在问“为什么我会得到两个不同的结果?”
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-03-13
    • 1970-01-01
    • 2011-12-27
    • 2013-09-18
    • 2011-03-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多