c#中的阴影 - 基本方法被调用而不是派生

时间:2015-06-22 08:47:00

标签: c# oop shadowing

我试图在c#中找出阴影的概念。这是我的代码,它的行为不像我期望的那样:

public class Animal
{
    public virtual void Foo()
    {
        Console.WriteLine("Foo Animal");
    }
}

public class Dog : Animal
{
    public new void Foo()
    {
        Console.WriteLine("Foo Dog");
    }
}

class Program
{
    static void Main(string[] args)
    {
        Dog dog1 = new Dog();
        ((Animal)dog1).Foo();
        Animal dog2 = new Dog();
        dog2.Foo();
    }
}

执行Main中的代码时,会调用基类Foo()中的Animal,并从我读到的关于阴影的内容Foo()来自{{应该调用1}}。有人可以解释我错过了什么吗?

我的例子是这样的: https://msdn.microsoft.com/en-us/library/ms173153.aspx

更新: 这是msdn的例子:

Dog

执行class Program { static void Main(string[] args) { BaseClass bc = new BaseClass(); DerivedClass dc = new DerivedClass(); BaseClass bcdc = new DerivedClass(); // The following two calls do what you would expect. They call // the methods that are defined in BaseClass. bc.Method1(); bc.Method2(); // Output: // Base - Method1 // Base - Method2 // The following two calls do what you would expect. They call // the methods that are defined in DerivedClass. dc.Method1(); dc.Method2(); // Output: // Derived - Method1 // Derived - Method2 // The following two calls produce different results, depending // on whether override (Method1) or new (Method2) is used. bcdc.Method1(); bcdc.Method2(); // Output: // Derived - Method1 // Base - Method2 } } class BaseClass { public virtual void Method1() { Console.WriteLine("Base - Method1"); } public virtual void Method2() { Console.WriteLine("Base - Method2"); } } class DerivedClass : BaseClass { public override void Method1() { Console.WriteLine("Derived - Method1"); } public new void Method2() { Console.WriteLine("Derived - Method2"); } } 时,会调用派生类中的bcdc.Method1(),这在我的示例中并非如此。

3 个答案:

答案 0 :(得分:0)

在您的情况下,dog1 Dog通常会让您" Foo Dog",但因为您明确告诉它是Animal,显示" Foo Animal"。有道理。

然后,使用dog2 Animal,你会期待" Foo动物"解雇,因为你说'嘿,你是一个动物",即使你virtual上有Animal(这表明派生类应该覆盖这个方法,然后根据类型决定在运行时调用的内容,你可以使用隐藏它的new

还是完全可以。在他们的示例中,bcdc的类型为BaseClass,但在运行时,因为它是Derived一个,而Method1正在使用virtual AND { {1}},在基础和派生上,它被调用。

因为它override没有覆盖虚拟,所以它会调用它所知道的唯一一个, Base 。如果不是将其定义为method2,而是BaseClass,它就会发现它DerivedClass

答案 1 :(得分:0)

在您执行((Animal)dog1).Foo()dog2.Foo()的示例中,动物的Foo方法被执行,因为当您运行应用程序时,CLR首先在base中搜索实现(因为对Animal的引用)然后检查它是否在派生类型中被覆盖,因为在这两种情况下,你没有覆盖它调用基本方法(Animal' Foo)而不是派生(Dog' Foo)的基类实现。 / p>

更新:

覆盖和新关键字之间的差异非常小。 当您执行覆盖时,无论您使用哪个引用都无关紧要,当对象为派生类型时,始终会调用重写方法。 如果你没有覆盖新的关键字,你实际上是在隐藏基类实现 我的意思是你在隐藏Derived类型的基类的实现而不是基础,所以当你使用base的引用来实现派生对象时 Base obj = new Derived(); 它总是调用基本方法,因为它无法在派生中找到重写方法。

答案 2 :(得分:0)

在行System.Net.WebUtility.HtmlEncode()中,首先将对象dog1转换为Dog from Dog类型。所以它在基类Animal中调用该方法。

如果您在狗类的 Foo 方法中使用覆盖而不是关键字,您将获得预期结果(即,将调用 Dog 类的 Foo 方法。

在您的代码((Animal)dog1).Foo()中,dog2将被创建为Animal dog2 = new Dog();的对象,而不是Animal。因此,调用Dog方法将调用Foo类中的方法。

您可以使用以下代码Animal Dog 类中调用 Foo 方法。此处可以从((Dog)dog2).Foo();转换为Animal类,因为变量Dog最初是从Dog类的构造函数

创建的
相关问题