OOP 方法隐藏和重载

6 c# overloading

我是编程新手。我学习书籍。有时一些例子会引起问题。求助,关于Habr的解释不是很清楚。在 habr 上找到了一个例子——关于 C# 的第四个问题。

class Program
    {
        static void Main(string[] args)
        {
            var x1 = new C(); 
            x1.Print(); //C

            B x2 = new C(); 
            x2.Print(); //C

            A x3 = new C(); 
            x3.Print(); //A
        }
    }



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

    class B : A
    {
        new public virtual void Print()
        {
            Console.WriteLine("B");
        }
    }

    class C : B
    {
        override public void Print()
        {
            Console.WriteLine("C");
        }
    }
Run Code Online (Sandbox Code Playgroud)

解释如下: 在第一次调用中,将显示“C”,因为对于 var 编译器将从表达式的右侧推断对象的类型,这将是类型 C。// 一切都清楚了.

对于第二次调用,还将显示值“C”,因为 CLR 将确定对象的实际类型是 C,并将调用必要的虚方法重载。//所以...

//进一步有点难以理解 在第三种情况下,将显示“A”,因为 B.Print 方法的声明(因此它在 C 中的重载)隐藏了 A.Print 方法。因此,CLR 不会将 B.Print 和 C.Print 视为重载并调用 A 类方法。

我已经在尝试逐步描述堆栈和堆的上下文中发生的事情:

x2:

  • 在堆上为类 C 的实例分配内存;
  • 默认构造函数将类 C 的实例写入此部分;
  • 将这块内存的链接写入堆栈上的变量 x2(类型 B),这是可能的,因为 B 是 C 的基类;
  • 接下来,您需要决定将调用所有 Print 方法中的哪个 Print 方法以及为什么。CLR查看变量的类型并尝试按类型调用方法,即在x2的情况下它是B.Print(),但由于我们拥有的链接是类C的实例,对于它方法重载,则调用C.Print()方法;

x3:

  • 在堆上为类 C 的实例分配内存;
  • 默认构造函数将类 C 的实例写入此部分;
  • 将这块内存的链接写入堆栈上的变量 x3(类型 A),这是可能的,因为 A 是 B 的基类,B 是 C 的基类;
  • 接下来,您需要决定将调用所有 Print 方法中的哪个 Print 方法以及为什么。CLR查看变量的类型并尝试按类型调用方法,即在x3的情况下它是A.Print(),但由于我们拥有的链接是类C的实例,对于它这个方法没有重载,然后调用A.Print()方法。

1)我的描述是真的吗?如果不是,请用这个例子解释它是如何工作的。

2) 您是否完全同意 Habr 上对答案的解释,或者您会删除/添加/替换某些内容吗?

小智 0

是的,从它的工作原理和链接来看,我的解释是正确的。

运行时(而不是编译器)根据该变量引用的对象的真实类型,确定通过变量调用该方法时要调用哪个版本的方法。(MS Visual C# 循序渐进 9ed,第 12 章使用继承)

为什么动态绑定在以下代码中没有按照我期望的方式工作?

CLR会检查整个继承链来确定调用哪个虚拟方法吗?