2010-03-16 288 views
5

這裏一個更基本的問題問MS近日接受採訪時多態性和C#

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

你爲什麼不試試呢? – 2010-03-16 15:12:25

+0

@Jeff:沒關係; B.Method1()仍然是被調用的函數。 – apandit 2010-03-16 15:15:04

+0

我認爲根據VMT(Vitual Method Table),重寫的方法的最新版本將被調用。 所以它可能是B.Method1() – TalentTuner 2010-03-16 15:16:10

回答

12
B.Method1(); 

被調用,因爲它正確地重寫虛擬方法A.Method1();

5

在這種情況下B.Method1被調用。這是因爲即使將變量鍵入爲A,實例的實際類型也是B。 CLR根據實例的實際類型而不是變量的類型以多態方式分派調用Method1

2

B.Method1()由於覆蓋而被調用。

3

規則是「在派生類最多的覆蓋成員」,在這種情況下將是「B」。

4

Method1B類將被命名,你可以通過運行下面的程序看:

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"); 
    } 
} 
1

B.Method1叫,因爲它是在類定義覆蓋。

1

的問題是有點ambigious ......但

obk.method2()被調用。反過來,它調用obk.Method1,由於它是B的一個實例,它已被B.Method1覆蓋。所以B.Method1是最終被調用的。

0

正如其他人所說,B.Method2被調用。這裏是一個信息的其他一些作品,使你明白這是怎麼回事:

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

這些都將調用B.Method1(),因爲它是正確的覆蓋。爲了調用A的方法1,必須有一個由B生成的base.Method1()調用(在B.Method1的實現中這通常並不總是完成)。

如果,但是,B是這樣定義的:

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

...那麼A的方法1()將被調用,因爲方法1實際上並沒有覆蓋,這是隱藏藏多態的規則之外。一般來說,這通常是一件壞事。並非總是如此,但要確保自己非常清楚自己在做什麼,以及爲什麼要這樣做。

另一方面,以這種方式使用也提供了一些有趣的面試問題。