2016-07-22 4 views
7

Ich habe diesen Code:C# 6 Fehler? virtuelle neue Methode seltsame Verhalten

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

gibt sie mir:

Foo 
Bar 
Baz 
Foo 
Foo 
Baz 

Aber ich dachte, es sein sollte:

Foo 
Bar 
Baz 
Foo 
Baz 
Baz 

Da Baz die zwingende ist Methode. Was passiert hier? Fehle ich etwas? Warum ist die Ausgabe für fooBaz.Test() "Foo" statt "Baz"?

Antwort

2

Wenn Sie das neue Schlüsselwort auf Bar.Test verwenden, sagen Sie, dass es keine Beziehung zu Foo.Test hat, außer dass es den gleichen Namen hat. Da Baz von Bar erbt, überschreibt es Bar.Test aber lässt Foo.Test unmodifiziert.

Wenn Sie fooBaz.Test aufrufen, sucht es die unmodifizierte Foo.Test Methode und druckt "Foo".

Wenn Sie barBaz.Test aufrufen, schlägt es die überschriebene Methode Bar.Test vor und druckt "Baz".

5

Buz ist die Methode überschrieben, deshalb

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

Baz gedruckt wird.

Aber Bar überschreibt nicht - es ist versteckt die Basismethode Test und macht die neue Methode virtuell. Dann überschreibt Baz die neue Methode von Bar, nicht die Methode von Foo. Also wenn Sie es so referenzieren: Foo fooBaz = new Baz(); dann wird fooBaz wie eine Instanz von Foo behandelt, die keine Ahnung von der Versteckmethode hat.

Die von Ihnen erwartete Ausgabe wird generiert, wenn Sie public new virtual void Test() in public override void Test() geändert haben.

Siehe auch die folgenden Themen:

+0

genau ist Baz die Methode überschrieben. Baz sollte zuerst vom Compiler berücksichtigt werden, oder? –

+0

Jon Skeet sollte das erklären, weil ich es immer noch nicht verstehe, hahahah –