2012-03-28 11 views
6

Ich habe meinen Code zu diesemabgeleiteten Klasse die falsche Methode

internal class Program 
{ 
    private static void Main(string[] args) 
    { 
     Child d = new Child(); 
     int i = 100; 
     d.AddToTotal(i); 

     Console.ReadKey(); 
    } 

    private class Parent 
    { 
     public virtual void AddToTotal(int x) 
     { 
      Console.WriteLine("Parent.AddToTotal(int)"); 
     } 
    } 

    private class Child : Parent 
    { 
     public override void AddToTotal(int number) 
     { 
      Console.WriteLine("Child.AddToTotal(int)"); 
     } 

     public void AddToTotal(double currency) 
     { 
      Console.WriteLine("Child.AddToTotal(double)"); 
     } 
    } 
} 

vereinfacht Das Problem ist, dass diese Anrufe

public void AddToTotal(double currency) 

obwohl ich es mit einem int nenne und es sollte

verwenden werden
public override void AddToTotal(int number) 

Die Verwendung des übergeordneten Elements gibt das erwartete Ergebnis zurück.

Parent d = new Child(); 
int i = 100; 
d.AddToTotal(i); 

Update:

Dank @Jan und @azyberezovsky für mich zum specification zeigt. Ich habe der Basisklasse eine virtuelle leere Methode hinzugefügt, um dies jetzt zu umgehen.

+2

Nun, ich war in der Lage, die Ergebnisse zu replizieren, und sicherzustellen, dass es in dem nicht nur ein Tippfehler war die Methode Name der int Überlastung unterschiedlich war. – Servy

+1

'd.AddToTotal (Nummer: i)' ruft die Int-Überladung wie erwartet auf, aber Sie sollten das nicht tun müssen ... – Servy

+3

Finden Sie diese Antwort für eine Erklärung: http://stackoverflow.com/a/1833268/25727 – Jan

Antwort

8

A member lookup eines Namens N in einem Typ T wird wie folgt verarbeitet:

Zunächst wird die Menge aller zugänglichen Mitglieder namens N in T deklariert und die Basistypen von T aufgebaut ist. Erklärungen, die einen überschreiben Modifizierer enthalten, sind ausgeschlossen aus dem Satz. Wenn keine Mitglieder mit dem Namen N existieren und zugänglich sind, erzeugt die Suche keine Übereinstimmung, und die folgenden Schritte werden nicht ausgewertet.

So wenn Sie Variable von Child Art

Child d = new Child(); 
int i = 100; 
d.AddToTotal(i); 

Methode public override void AddToTotal(int number) wird von Satz ausgeschlossen, und wir haben nur eine Methode mit dem Namen N links. Int wird implizit in double umgewandelt, so dass keine Fehler aufgetreten sind.

+0

Ich finde es sehr merkwürdig, dass die Überladungsauflösung neuen Methoden gegenüber überschriebenen Methoden eine höhere Priorität einräumt, aber anscheinend tut es ... seltsam. Wer weiß, was dahinter steckt? – Servy

+1

@Servy siehe diese Antwort von Eric Lippert für die Begründung: http://StackOverflow.com/A/1833866/53777 –

+4

@Servy: Viele Leute finden diese Wahl ungerade, aber es gibt zwei sehr gute Gründe dafür. Der erste Grund ist, dass * der Entwickler, der die abgeleitete Klassenmethode geschrieben hat, mehr Informationen hat als der Entwickler, der die Basisklassenmethode geschrieben hat. * Insbesondere weiß der Entwickler der abgeleiteten Klasse, was die Implementierungsdetails der abgeleiteten Klasse sind, aber der Basisklassenentwickler nicht. Überladungsauflösung sollte die Methode auswählen, die von dem Typ geschrieben wurde, der am meisten über das Objekt wusste, das der Benutzer tatsächlich verwendet. –

1

This answer zu this question erklärt die technischen Gründe, warum dies passiert. Ich habe die Antwort inline hier für die Bequemlichkeit enthalten, aber alle Kredit ist aufgrund tvanfosson.

Siehe Abschnitt der # Language Specification C auf Member Lookup und Overload Resolution. Die Überschreibungsmethode der abgeleiteten Klasse ist aufgrund der Regeln für die Membersuche nicht geeignet, und die Basisklassenmethode ist nicht die beste Übereinstimmung basierend auf den Regeln für die Überladungsauflösung .

Abschnitt 7,3

Zunächst wird die Menge aller zugänglich (Abschnitt 3.5) Mitglieder N genannt in T und den Basistypen deklariert (Abschnitt 7.3.1) von T aufgebaut. Deklarationen, die einen Überschreibungsmodifikator enthalten, werden vom -Set ausgeschlossen. Wenn keine Mitglieder mit dem Namen N vorhanden sind und auf sie zugegriffen werden kann, erzeugt die Suche keine Übereinstimmung und die folgenden Schritte werden nicht ausgewertet.

Abschnitt 7.4.2:

da jeder dieser Kontexte definieren den Satz von Kandidatenfunktionsmitgliedern und die Liste der Argumente in seiner eigenen einzigartigen Art und Weise, in der oben aufgeführt Detail in den Abschnitten beschrieben. Zum Beispiel enthält der Satz von Kandidaten für einen Methodenaufruf keine mit überschriebenen Methoden (Abschnitt 7.3) und Methoden in einer Basisklasse sind keine Kandidaten , wenn eine Methode in einer abgeleiteten Klasse anwendbar ist (Abschnitt 7.5.5.1). (Hervorhebung von mir)

Verwandte Themen