2016-07-22 18 views
7

我有這樣的代碼:c#6錯誤?虛擬新方法奇怪的行爲

using System; 

namespace Test 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Foo foo = new Foo(); 
      Bar bar = new Bar(); 
      Baz baz = new Baz(); 
      Foo fooBar = new Bar(); 
      Foo fooBaz = new Baz(); 
      Bar barBaz = new Baz(); 

      foo.Test(); 
      bar.Test(); 
      baz.Test(); 
      fooBar.Test(); 
      fooBaz.Test(); 
      barBaz.Test(); 

      Console.ReadLine(); 
     } 
    } 

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

    internal class Bar : Foo 
    { 
     public new virtual void Test() 
     { 
      Console.WriteLine("Bar"); 
     } 
    } 

    internal class Baz : Bar 
    { 
     public override void Test() 
     { 
      Console.WriteLine("Baz"); 
     } 
    } 
} 

它輸出我:

Foo 
Bar 
Baz 
Foo 
Foo 
Baz 

但是,我認爲它應該是:

Foo 
Bar 
Baz 
Foo 
Baz 
Baz 

因爲巴茲被重寫方法。這裏發生了什麼? 我錯過了什麼嗎?爲什麼fooBaz.Test()的輸出是「Foo」而不是「Baz」?

回答

2

當您在Bar.Test上使用新關鍵字時,您說它與Foo.Test沒有任何關係,只是它具有相同的名稱。由於Baz從Bar繼承,因此它將覆蓋Bar.Test,但不修改Foo.Test

當您致電fooBaz.Test時,它會查找未修改的Foo.Test方法並打印「Foo」。

當您致電barBaz.Test時,它會查找覆蓋範圍Bar.Test方法並打印「Baz」。

5

Buz壓倒一切的方法,這就是爲什麼

Bar barBaz = new Baz(); 
barBaz.Test(); 

將打印Baz

Bar不是重寫 - 它是隱藏基本方法Test並使新方法虛擬。然後Baz覆蓋從Bar的新方法,而不是從Foo的方法。 因此,如果你參考它是這樣的:Foo fooBaz = new Baz();然後fooBaz被視爲Foo的實例,它不知道隱藏方法。

如果您將public new virtual void Test()更改爲public override void Test(),則會生成您期望的輸出。

參見以下主題:

+0

準確,巴茲被覆蓋方法。 Baz應該首先由編譯器考慮,不是嗎? –

+0

喬恩Skeet應該解釋這一個,因爲我仍然不明白,哈哈哈 –