Warum ist das überschreiben der statischen Methode sind erlaubt in C#
protected static new void WhyIsThisValidCode()
{
}
Warum sind Sie erlaubt das überschreiben von statischen Methoden?
Nichts als bugs kommen kann, aus, es doensn nicht funktionieren, wie Sie denken würde.
Nehmen Sie die folgenden Klassen.
class BaseLogger
{
protected static string LogName { get { return null; } }
public static void Log(string message) { Logger.Log(message, LogName); }
}
class SpecificLogger : BaseLogger
{
protected static string LogName { get { return "Specific"; } }
}
dies ist alowed, und der code
SpecificLogger.Log("test");
ist altso sind erlaubt, aber es muss nicht das tun, was würden Sie denken, indem Sie sich den code.
ruft es Logger.Log
mit LogName = null
.
So, warum ist dies erlaubt?
- Wie schon andere gesagt haben, ist dies nicht überschreiben - und es funktioniert genau so, wie ich es erwarten. Bitte nicht davon ausgehen, jeder denkt das gleiche wie Sie tun.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Den
new
Schlüsselwort nicht eine Methode überschreiben. Sie erstellt stattdessen eine neue Methode mit dem gleichen Namen, die unabhängig von der ursprünglichen. Es ist nicht möglich, das überschreiben einer statischen Methode, weil Sie nicht virtuellSind Sie nicht überschreiben, Sie sind versteckt. Eine normale Methode würde zeigen genau das gleiche Verhalten, es gibt also nichts konkretes zu statischen Methoden hier.
Verstecken ist nur nützlich in einigen Fällen. Das einzige, wo ich kam ganz Häufig macht der Rückgabetyp genauer in einer abgeleiteten Klasse. Aber ich hatte nie das auftreten mit statischen Methoden.
Einer Gegend, wo statische Funktionen, die einen bestimmten Namen haben, könnte nützlich ist, wenn Sie mit Reflexion und wollen zu bekommen Informationen auf jede Klasse durch die Rückkehr aus einer Methode. Aber natürlich in den meisten Fällen ein Attribut besser passt.
Und es ist nicht wahrscheinlich, um Fehler erstellen, da dein code erzeugt eine compiler-Warnung:
Und wenn Sie
new
sollten Sie wissen, was Sie tun.Andere haben darauf hingewiesen, dass dies nicht überschreiben, aber das lässt immer noch Ihrer ursprünglichen Frage: warum sind Sie in der Lage, es zu tun? (Aber die Frage ist wirklich, "warum kann Sie ausblenden statische Methoden".)
Es ist eine unvermeidliche Funktion der Unterstützung der unabhängigen Versionierung der Komponente, enthalten Basis-Klassen und Komponenten, mit denen diese Basis-Klassen.
Zum Beispiel vorstellbar, dass Komponente CompB enthält die Basis-Klasse, und einige andere Komponente CompD enthält eine abgeleitete Klasse. In version 1 des CompB, es könnte nicht jede Eigenschaft, die man als LogName. Der Autor CompD entscheidet, fügen Sie eine statische Eigenschaft namens " LogName.
Die kritische Sache zu verstehen, ist an dieser Stelle, dass der Autor von v1 von CompD hatte nicht die Absicht, zu ersetzen oder ausblenden-Funktion der Basis-Klasse - gab es kein Mitglied namens LogName in der Basisklasse, wenn Sie schrieb, dass code.
Stellen Sie sich nun vor, dass eine neue version der CompB-Bibliothek veröffentlicht wird. In dieser neuen version hat der Autor Hinzugefügt LogName-Eigenschaft. Was soll passieren, CompD? Die Optionen erscheinen:
.NET zu tun wählt 3. (Und er tut das mit der Statik und nicht-Statik. Wenn Sie wollen, Verhalten 2 - Ersatz - mit nicht-Statik, dann die Basis sein
virtual
und der abgeleiteten Klasse hat, um mark die Methode alsoverride
deutlich zu machen, dass Sie bewusst überschreiben einer Methode in der Basisklasse. C# wird nie eine abgeleitete Klasse die replace-Methode einer Basisklasse die Methode, es sei denn, die abgeleitete Klasse explizit darauf hingewiesen, dass dies ist, was Sie wollten.) Dies ist wahrscheinlich sicher, weil zwei Mitglieder unabhängig sind - die Basis LogName gar nicht existieren, an der Stelle, wo die abgeleitete einer eingeführt wurde. Und dies ist vorzuziehen, um einfach zu brechen, da die Letzte version der Basis-Klasse eingeführt, ein neues Mitglied.Ohne diese Funktion, wäre es unmöglich, dass neue Versionen von der .NET Framework, um neue Mitglieder zu den bestehenden Basisklassen, ohne dass dies eine bedeutende änderung.
Ihnen sagen, dass das Verhalten ist nicht, was Sie erwarten. Eigentlich ist es genau das, was ich erwarten würde, und was würden Sie wahrscheinlich wollen in der Praxis. Die BaseLogger hat keine Ahnung, dass die SpecificLogger eingeführt hat seine eigenen LogName-Eigenschaft. (Es gibt keinen Mechanismus, der es konnte, weil Sie nicht überschreiben kann statische Methoden.) Und wenn der Autor der SpecificLogger schrieb, dass LogName Eigenschaft, denken Sie daran, dass Sie schriftlich gegen die v1 von BaseLogger, die nicht über eine LogName, so dass Sie nicht beabsichtigen, das es ersetzen sollte, die Basis-Methode. Da weder die Klasse will Ersatz, klar Ersatz wäre das falsche.
Ist das einzige Szenario, in, die, sollten Sie jemals am Ende in dieser situation ist, dass die beiden Klassen sich in unterschiedlichen Komponenten. (Natürlich können Sie erfinden ein Szenario, wenn Sie sind in der gleichen Komponente, aber warum sollte man das ständig tun? Wenn Sie beide Stücke von code und lassen Sie Sie in einer einzigen Komponente, es würde verrückt sein, Sie jemals zu tun.) Und so BaseLogger seine eigenen LogName-Eigenschaft, die ist, was genau passiert. Möglicherweise haben Sie geschrieben:
aber der C# - compiler erkennt, dass SpecificLogger nicht eine Login-Methode, so stellt sich dies in:
weil das ist, wo die Log-Methode definiert ist.
Also bei der Definition einer Methode in einer abgeleiteten Klasse, die nicht versucht, zu überschreiben einer bereits vorhandenen Methode der C# - compiler gibt an, dass diese in den Metadaten. (Es gibt eine "newslot" - Einstellung in der Methode Metadaten, die sagt, diese Methode soll nagelneu sein, ohne Beziehung zu irgend etwas in der Basisklasse.)
Doch so haben Sie ein problem, wenn Sie kompilieren wollen CompD. Sagen wir mal du hast einen bug-report wegen einiger völlig andere bit-code, und Sie müssen eine neue version von CompD. Kompilieren Sie es gegen die neue verison von CompB. Wenn der code, den Sie geschrieben haben war nicht erlaubt, Sie würden nicht tatsächlich in der Lage sein, um alten code bereits kompiliert funktionieren würde, aber Sie wäre nicht in der Lage zu kompilieren, neue Versionen des Codes, die wäre ein bisschen verrückt.
Und so, um dies zu unterstützen (ehrlich gesagt etwas obskuren) Szenario, erlauben Sie Ihnen, dies zu tun. Sie generiert eine Warnung, um Sie wissen zu lassen, dass Sie habe eine Namensgebung clash hier. Sie benötigen zur Versorgung der
new
Schlüsselwort, um es loszuwerden.Dies ist eine obskure Szenario, aber wenn Sie möchten, dass die Vererbung über komponentengrenzen hinweg, Sie brauchen dies, sonst ist die Zugabe von neuen public oder protected member einer Basisklasse immer eine bedeutende änderung. Deshalb ist dies hier. Aber es ist schlechte Praxis immer auf Sie verlassen, daher die Tatsache, dass Sie eine compiler-Warnung. Die Nutzung der
new
Schlüsselwort, um loszuwerden, die Abmahnung sollte immer nur eine Notlösung.Unter dem Strich ist dies: diese Funktion existiert nur aus einem Grund, und das ist, um Sie aus einem Loch in Situationen, in denen eine neue version einer Basisklasse Hinzugefügt hat, ein Mitglied, das zuvor nicht existiert haben, und die Auseinandersetzungen mit einem Mitglied, das sich bereits auf die abgeleitete Klasse. Wenn das nicht die situation, Sie in sind, verwenden Sie nicht diese Funktion.
(Ich denke, Sie sollte eigentlich ein Fehler ausgegeben, sondern als eine Warnung, wenn man neue, um diese besser klar.)
Statische Methoden und Felder gehören nicht zu Instanzen der Klasse, sondern zur Klasse Definitionen. Statische Methoden nicht Teil spielen in der virtuellen dispatching-Mechanismus und sind nicht Teil der Tabelle virtueller Methoden.
Sind Sie nur Methoden und Felder, die von bestimmten Klassen.
Kann es so Aussehen wie die Methoden und Felder sind "geerbt", weil Sie tun können
SpecificLogger.Log()
, aber das ist etwas zu halten, Sie beziehen sich auf die Basis-Klasse die ganze Zeit.Statische Methoden und Felder sind nur Globale Methoden und Felder, nur die OO-Art.
Sind Sie nicht überschreiben Sie die Eigenschaft in der Basisklasse, aber statt es zu verbergen. Die eigentliche Eigenschaft zur Laufzeit verwendet, hängt davon ab, welche Schnittstelle Sie arbeiten gegen. Das folgende Beispiel zeigt:
In Ihrem code die Log-Methode ist tatsächlich arbeiten gegen die BaseLogger interface - weil die Log-Methode ist Teil der BaseLogger Klasse.
Statische Eigenschaften und Methoden können nicht überschrieben werden, und wenn Sie wollen, zu verstecken, eine Eigenschaft, die Sie verwenden sollten, die
new
Schlüsselwort zu Kennzeichnen, dass Sie etwas zu verbergen.meiner überraschung folgende code ist erlaubt und kompiliert ohne Fehler auf .net Framework 4.5.1, VS 2013.