多态性和C#

5

最近在微软面试中又有一个基础问题被问到:

class A {
    public virtual void Method1(){}

    public void Method2() {
        Method1();
    }
}

class B:A {
    public override void Method1() { }
}

class main {
    A obk = new B();
    obk.Method2(); 
}

那么哪个函数被调用?抱歉打错字了。

22
为什么不尝试一下呢? - Mark Seemann
@Jeff:无所谓,B.Method1()仍然是被调用的函数。 - apandit
我认为根据VMT(虚拟方法表)的规定,将调用被覆盖方法的最新版本。因此可能是B.Method1()。 - TalentTuner
8个回答

12
B.Method1();

该方法被调用,因为它正确地覆盖了虚拟方法A.Method1();


5
在这种情况下,调用的是B.Method1。这是因为尽管变量的类型为A,但实例的实际类型是B。CLR根据实例的实际类型而不是变量的类型对Method1进行多态分派。

4
运行以下程序,可以看到来自类B的Method1将被调用:

B类中的Method1将被调用,如下所示:

class Program
{
    static void Main(string[] args)
    {
        var b = new B();
        b.Method2();

        Console.ReadLine();
    }
}

class A 
{ 

    public virtual void Method1()
    {
         Console.WriteLine("Method1 in class A");
    } 

    public void Method2() 
    { 
         Method1(); 
    } 
}

class B : A 
{ 
    public override void Method1() 
    { 
         Console.WriteLine("Method1 in class B"); 
    } 
} 

3
规则是“在最终派生类中覆盖成员”,在此情况下为“B”。

2
由于覆盖,B.Method1()被调用。

1

调用B.Method1是因为它在类定义中被覆盖了。


1
问题有点模糊,但是...
调用obk.method2()。接着,它调用obk.Method1,由于它是B的实例,已经被B.Method1覆盖。因此最终调用的是B.Method1。

0

正如其他人所说,B.Method2被调用。以下是一些其他信息,以便您了解正在发生的情况:

((A)B).Method2();
B.Method2();

这两个都会调用B.Method1(),因为它被正确地重写了。为了调用A的Method1,必须从B中进行base.Method1()调用(通常但不总是在B.Method1的实现中完成)。

然而,如果B是这样定义的:

class B:A {
new public void Method1() { }

...那么将调用A的Method1(),因为Method1实际上并没有被覆盖,它被隐藏和藏起来在多态规则之外。一般来说,这通常是一个不好的做法。并非总是如此,但如果您像这样做任何事情,请确保您非常清楚自己在做什么以及为什么要这样做。

另一方面,在这种方式中使用new也会产生一些有趣的面试问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接