c#菜鸟:这个代码并不像我预期的那样工作。。。为什么?

c#菜鸟:这个代码并不像我预期的那样工作。。。为什么?,c#,C#,为了进一步了解C#中不太常见的构造,我在codingsight.com上遇到了以下代码示例: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace ConsoleApp2 { class Program { static void Main(string[] args

为了进一步了解C#中不太常见的构造,我在codingsight.com上遇到了以下代码示例:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ConsoleApp2
{
    class Program
    {
        static void Main(string[] args)
        {
            MyClassB b = new MyClassB();
            MyClassA a = b;
            a.abc();
            Console.ReadLine();
        }
    }

    class MyClassA
    {
        public MyClassA()
        {
            Console.WriteLine("constructor A");
        }

        public void abc()
        {
            Console.WriteLine("A");
        }
    }

    class MyClassB : MyClassA
    {
        public MyClassB()
        {
            Console.WriteLine("constructor B");
        }

        public void abc()
        {
            Console.WriteLine("B");
        }
    }
}
挑战在于预测产量。在控制台中运行代码时会出现:

constructor A
constructor B
A
我最后一分钱打赌输出的第三行是“B”,或“单位化变量”错误,但实际上是“A”。为什么?

为什么?

因为它是.NET语言的一个概念,叫做。它的定义是这样的,微软并没有给出这样做的理由。他们本可以选择任何其他行为,但他们没有

你在评论中说:

计算机所做的是“某种东西”,但显然不是代码的意图

事实上,我们不知道目的是什么。我们需要询问代码片段的作者。我想说,这是有意的,因为这是一个很大的问题,看看是否有人理解了继承的原则

在标题中,你提到了一个警告——而这个警告正是对作者的警告,他没有充分表达他的意图。或者这是对读者的一个警告,作者没有充分表达他的意图

警告是

警告CS0108:'MyClassB.abc()'隐藏继承的成员'MyClassA.abc()'。如果要隐藏,请使用新关键字

这个警告还告诉我们,作者应该在
MyClassB.abc()
上使用
new
关键字来明确地告诉读者他在使用“通过继承隐藏”

那么,还有什么选择呢?如果您希望按照自己的期望继承,
MyClassA.abc()
需要标记为
virtual

hoewever,仅此更改并不能按照您的预期修复继承。还有另一个编译器警告

警告CS0114:'MyClassB.abc()'隐藏继承的成员'MyClassA.abc()'。要使当前成员覆盖该实现,请添加override关键字。否则,添加新关键字

这清楚地表明
MyClassB.abc()
也需要标记为
override

看来你对这句话最困惑了

那句话相当于

MyClassA a = (MyClassA) b;
但演员阵容是多余的,因为:

隐式引用转换为:

[……]

从任何类别类型
S
到任何类别类型
T
,前提是
S
源自
T


(其中S是MyClassB,T是MyClassA)

为什么会出现意外情况?计算机正在执行您让它执行的操作。您必须将MyClassA.abc标记为
virtual
,将MyClassB.abc标记为
override
,才能将输出标记为“B”。基本上,您必须明确地告诉编译器MyClassB.abc替换了MyClassA的版本。计算机所做的是“某些事情”,但显然不是代码的意图。显然,创建代码示例是为了演示“=”操作符在与对象一起使用时的一些奇怪行为。最符合目标的修复方法是使用.clone()接口。好吧,听起来你比我更了解,也比编译器更了解。;)你说“清楚”,但我一点也不清楚。因为我读C#,就像你们的计算机一样,而不是“你们个人头脑中的任何其他编程语言”)通常人们不会期望从
A
上下文中神奇地获得
B
行为。也许这会让事情更清楚:看,问题4。我删除了关于警告的文本,因为我自己已经解决了该部分。不幸的是,我也超过了5分钟的时间来更正问题标题。实际上,这个代码示例测试了OOP的3个方面的知识:-调用继承对象的构造函数是否调用父对象的构造函数(是的,它调用父对象的构造函数)。还有其他OOP实现要求您使用诸如继承的语句;要做到这一点。我正在努力解决的部分是“=”操作符在与对象一起使用时的确切行为。它与变量不同。作为问题的作者,您可以在不受任何时间限制的情况下编辑您的问题。只有注释有5分钟的限制。@Nimral:我添加了关于隐式引用转换的内容,这就是我要找的!现在对我来说,程序的输出是有意义的。只是想看看我是否做对了:关于使用“new”的警告与问题无关?它标记了一个单独的错误(不清楚的继承)。其他OOP实现不会发出警告,他们会得出结论,MyObjectB中的abc是为了在没有任何警告的情况下,完全用myObjectA的相同名称覆盖该方法。为什么任何人都要覆盖一个方法,然后不使用它?
MyClassA a = (MyClassA) b;