2

在基于类型引用对象的方法覆盖的情况下,将决定保持方法调用。在方法隐藏的情况下,将根据对象方法调用的类型来决定。

谁能解释一下覆盖+隐藏中的方法调用决策。

public class Base
    {
        public virtual void DoIt()
        {
        }
    }

    public class Derived : Base
    {
        public  override void DoIt()
        {
        }
    }

    public class Derived1 : Derived
    {
        public new void DoIt()
        {
        }
    }
    class Program
    {
        static void Main(string[] args)
        {

            Base b = new Derived();
            Derived d = new Derived();
      #1    b.DoIt();                      // Calls Derived.DoIt
      #2    d.DoIt();                     // Calls Derived.DoIt
            b = new Derived1();
            d = new Derived1();
      #3    b.DoIt();                      // Calls Derived.DoIt
      #4    d.DoIt();
}
}

#1 和 #2 调用 Derived.DoIt 因为运行时多态性。

#4 称为 Derived.DoIt,因为 d 是 Derived 类型(方法隐藏)。

但是为什么#3 调用 Derived.DoIt。

在c#中覆盖加隐藏的情况下调用顺序是什么?

提前致谢

4

3 回答 3

1

因为#3 是Base类型的一个实例。在这里,最后一个派生方法Base驻留在Derived类中,因此它被调用。

new/方法隐藏/阴影不同于方法覆盖,因为覆盖意味着您正在自定义基本方法,而new意味着您只是为相同的方法名称提供不同的实现。

于 2016-05-08T09:23:13.513 回答
1

在方法覆盖中,在运行时决定要调用哪个类型的方法,但是方法隐藏或隐藏是编译时的事情,编译器在编译时知道要调用哪个类型的方法,当您new在方法的派生类型中使用关键字时签名而不是覆盖,这意味着如果您使用基类的引用调用它将调用基类实现,如果您使用派生类引用它将调用派生类方法实现。

派生类实现对基类隐藏。

如果你这样写:

b = new Derived1();
b.DoIt() // (run-time) will call Dervied method implementation as Dervied has overridden 
        // so calling via base reference will call overridden implementation if any
       //otherwise base class implementation will get called

Derived1 d1 = (Derived1)b;
d1.DoIt(); // (compile time) will call Derived1 method implementation due to hiding in Derived1
Derived d = (Derived)b;
d.DoIt(); // (run-time) will call Derived method implementation due to override 
于 2016-05-08T09:27:07.770 回答
0

#3 调用 Derived.DoIt() 因为该方法只是隐藏的,如果使用适当的强制转换,它仍然可以在外部调用。变量 b 的类型是 Base,因此您正在访问 Base 可用的方法。这是通过 Derived 覆盖的结果,因此您的结果是来自 Derived.DoIt 的结果。如果您有一个 Derived1 类型的变量并在那里调用 DoIt,那么 Derived1.DoIt 会被调用。

public class Base
{
    public virtual void DoIt()
    {
        Console.WriteLine("Base.DoIt was called!");
    }
}

public class Derived : Base
{
    public override void DoIt()
    {
        Console.WriteLine("Derived.DoIt was called!");
    }
}

public class Derived1 : Derived
{
    public new void DoIt()
    {
        Console.WriteLine("Derived1.DoIt was called!");
    }
}
class Program
{
    static void Main(string[] args)
    {

        Base b = new Derived();
        Derived d = new Derived();
        Console.WriteLine("#1");
        b.DoIt();                      
        Console.WriteLine("#2");
        d.DoIt();                     
        b = new Derived1();
        d = new Derived1();
        Console.WriteLine("#3");
        b.DoIt();                    
        Console.WriteLine("#4");
        d.DoIt();
        Console.WriteLine("#5");
        Derived1 e = new Derived1();
        e.DoIt();
        Console.ReadKey();
    }
}
于 2016-05-08T09:19:23.223 回答