2

我试图弄清楚 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()from 。Dog有人可以解释我错过了什么吗?

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

更新:这是来自 msdn 的示例:

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()执行时,Method1()从派生类被调用,在我的示例中不是这种情况。

4

3 回答 3

0

在您的情况下,dog1Dog通常会让您获得“Foo Dog”,但是因为您明确告诉它是 an Animal,所以它会显示“Foo Animal”。说得通。

然后,使用dog2, 这是一个Animal,您期望“Foo 动物”触发,因为您说“嘿,您是动物”,即使您有virtualon Animal(这表明派生类应该覆盖此方法,并且那么调用什么的分辨率将根据类型在运行时发生),您使用newwhich 隐藏它。


仍然完全可以。在他们的示例中,bcdc是 type BaseClass,但在运行时,因为它是Derived一个,并且在基础和派生上Method1使用virtualAND override,所以它被调用。

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

于 2015-06-22T09:02:42.157 回答
0

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

更新 :

override 和 new 关键字之间的区别非常小。当您进行覆盖时,无论您使用哪个引用,当对象是派生类型时,它总是调用被覆盖的方法。如果你没有重写新关键字,你实际上隐藏了基类实现我的意思是你隐藏了派生类型而不是基类的基类实现,所以当你使用基类的引用作为派生对象时
Base obj = new Derived(); 它总是调用基方法,因为它在派生中找不到被覆盖的方法。

于 2015-06-22T09:21:22.487 回答
0

在这一行中((Animal)dog1).Foo(),首先将对象 dog1 从 Dog 转换为 Animal 类型。所以它调用基类Animal中的方法。

如果在 dog 类的Foo方法中使用override而不是new关键字,您将得到预期的结果(即会调用Dog类的Foo方法)。

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

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

于 2015-06-22T09:51:24.470 回答