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!
"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 –