2016-04-04 6 views
4
namespace test 
{ 
    class Program 
    { 

     static void Main(string[] args) 
     { 
      Derived obj = new Derived(); 
      int i = 10; 
      obj.Foo(i); 

      Console.ReadLine(); 
     } 

    } 
    class Base 
    { 
     public virtual void Foo(int i) 
     { 
      Console.WriteLine("Base:Foo()"); 
     } 
    } 
    class Derived:Base 
    { 
     public override void Foo(int i) 
     { 
      Console.WriteLine("Foo(int)"); 
     } 
     public void Foo(object i) 
     { 
      Console.WriteLine("Foo(object)"); 
     } 
    } 
} 

Ausgabe des Programms nach mir sollte Foo (int) sein, aber Ausgabe kommt als Foo (Objekt) Bitte helfen Sie mir die diffrence VerständnisWarum funktioniert das Überladen von Methoden in diesem C# -Programm nicht?

+1

"Schließen ist besser als weit weg." Der Compiler bevorzugt die zuerst in der abgeleiteten Klasse deklarierte Methode, die Objektüberladung. Für mehr: http://ericlippert.com/2013/12/23/closer-is-better/#more-1806 –

Antwort

6

Gute Frage in der Ausgabe, ich Ihre Ergebnisse reproduzieren kann. Wenn man einen Blick auf die C# specifications nimmt man die folgenden Schnipsel finden:

7.5.3 Überlast Auflösung

Zum Beispiel die Menge der Kandidaten für einen Methodenaufruf nicht umfassen Verfahren gekennzeichnet override (§7.4) und Methoden in einer Basisklasse sind keine Kandidaten, wenn eine Methode in einer abgeleiteten Klasse anwendbar ist (§7.6.5.1).

7,4 Mitglied Lookup

Andernfalls besteht die Menge aller zugänglichen (§3.5) Mitglieder genannt N in T, einschließlich geerbten Mitglieder und den zugänglichen N in Objekt namens Mitglieder. Wenn T ein konstruierter Typ ist, wird die Menge der Elemente durch Substitution von Typargumenten wie in §10.3.2 beschrieben erhalten. Mitglieder, die einen Umgehungsmodifizierer enthalten, sind aus dem Set ausgeschlossen.

7.6.5.1 Aufrufe von Prozeduren

Die Menge von in Frage kommenden Methoden reduziert wird nur Methoden aus den abgeleiteten Typen enthalten: Für jede Methode CF in dem Satz, wobei C die ist Typ, in dem die Methode F deklariert wird, Alle Methoden, die in einer Basis Typ von C deklariert sind, werden aus der Menge entfernt. Wenn C außerdem eine Klassenart ist, die kein Objekt ist, werden alle Methoden, die in einem Schnittstellentyp deklariert sind, aus der Menge entfernt.

Klingt ein bisschen kompliziert? Auch scheinen die C# Designer so und in der ‚hilfreich‘ Notiz setzen zu denken:

7.6.5.1 Methode Anrufungen

Die intuitive Wirkung der Auflösung oben beschriebenen Regeln wird als folgt: Um Lokalisieren Sie die bestimmte Methode aufgerufen durch eine Methode Aufruf, beginnen mit dem Typ durch die Methode Aufruf und Vererbung der Vererbungskette bis mindestens eine anwendbar, zugänglich, Non-Override-Methode Erklärung gefunden. Führen Sie dann Inferenz- und Überladungsauflösung in der Menge der anwendbaren, zugänglichen, nicht überschreibenden Methoden aus, die in diesem Typ deklariert sind, und rufen Sie die so ausgewählte Methode auf.Wenn keine Methode gefunden wurde, versuchen Sie stattdessen, den Aufruf als Erweiterungsmethodenaufruf zu verarbeiten.

Wenn wir einen Blick auf Ihre abgeleitete Klasse nehmen, sehen wir zwei mögliche Methoden für C# verwenden:

A) public override void Foo(int i) 
B) public void Foo(object i) 

Lassen Sie uns das letzte Checkliste verwenden!

Anwendbarkeit - Sowohl A als auch B sind anwendbar - (beide sind ungültig, beide heißen 'Foo' und beide können einen ganzzahligen Wert annehmen). Erreichbarkeit - Sowohl A als auch B sind zugänglich (öffentlich) Nicht überschrieben - Nur B wird nicht überschrieben.

Aber warten Sie vielleicht sagen! A ist spezifischer als B!

Richtig, aber dass die Prüfung wird nur nach wir Option A. Als Eric Lippert (einer der Designer) außer Acht gelassen habe es ausdrückt Closer is always better than farther away. (Danke Anthony Pegram)

Nachtrag

Es gibt immer the 'new' keyword:

class Derived : Base 
{ 
    public new void Foo(int i) 
    { 
     Console.WriteLine("Foo(int)"); 
    } 

    public void Foo(object i) 
    { 
     Console.WriteLine("Foo(object)"); 
    } 
} 

Obwohl die Besonderheiten, die am besten links für eine andere Frage!

0

Der einfache Datentyp int stammt vom Objekt ab. Sie überschreiben die Funktion und überladen auch die Parameterliste. Da der Funktionsname mit einer anderen Signatur identisch ist, erlaubt der Compiler dies. Für einfache Objekte werde ich eine Kopie der Parametersignatur in der einfachsten Form in der Methodentabelle gespeichert.

Verwandte Themen