Warum brauchen wir die neue keyword-und warum ist das Standard-Verhalten zu verbergen und nicht überschreiben?
Ich mich mit diesem blog-post und hatte folgende Fragen:
- Warum brauchen wir die
new
Schlüsselwort, ist es nur um anzugeben, dass eine Basis-Methode der Klasse wird ausgeblendet. Ich meine, warum brauchen wir es? Wenn wir nicht dieoverride
Stichwort, nicht wir verstecken die Basisklasse die Methode? - Warum ist der default in C# zu verbergen und nicht überschreiben? Warum haben die Designer implementiert, die es auf diese Weise?
Eine etwas interessante Frage (für mich) ist, warum verbergen legal ist. Es ist in der Regel ein Fehler (damit der compiler die Warnung), selten wollte und immer problematisch am besten.
InformationsquelleAutor Sandbox | 2010-06-25
Du musst angemeldet sein, um einen Kommentar abzugeben.
Gute Fragen. Lassen Sie mich neu-Zustand.
Lassen Sie mich zu beantworten diese Frage mit einem Beispiel. Sie haben eine Schnittstelle von CLR-v1:
Super. Jetzt in CLR-v2-Sie haben Generika und Sie denken, "Mann, wenn nur wir hatten Generika in v1 hätte ich das eine generische Schnittstelle. Habe ich aber nicht. Ich sollte etwas machen, kompatibel mit es nun, dass ist allgemein so, dass ich die Vorteile von Generika ohne rückwärts-Kompatibilität mit code, der erwartet, dass IEnumerable."
Was Sie gehend zu nennen, die GetEnumerator-Methode der
IEnumerable<T>
? Denken Sie daran, Sie wollen es zu verbergen GetEnumerator auf die nicht-generische Basis-Schnittstelle. Sie nie wollen das Ding genannt zu werden, es sei denn, Sie sind ausdrücklich in eine rückwärts-compat situation.Dass allein rechtfertigt Methode versteckt. Für weitere Gedanken über Rechtfertigungen der Methode versteckt sehen mein Artikel zu dem Thema.
Denn wir möchten Sie darauf aufmerksam machen, dass Sie etwas versteckt sind und möglicherweise tun Sie es versehentlich. Denken Sie daran, Sie vielleicht etwas zu verbergen habe versehentlich aufgrund eines Bearbeiten, um die base-Klasse von jemand anderem, anstatt durch Bearbeiten Sie die abgeleitete Klasse.
Gleichen Grund. Sie könnten etwas zu verbergen versehentlich weil Sie gerade abgeholt, eine neue version einer Basisklasse. Dies geschieht die ganze Zeit. FooCorp macht eine Basisklasse B. BarCorp macht eine abgeleitete Klasse D-mit einer Methode, die Bar, weil Ihre Kunden wie, die Methode. FooCorp sieht, und sagt, hey, das ist eine gute Idee, wir können diese Funktionalität in der Basisklasse. Sie tun dies und versenden einer neuen version von Foo.DLL und wenn BarCorp nimmt die neue version, wäre es schön, wenn Sie erfuhren, dass Ihre Methode, die jetzt versteckt sich die Basis-Methode der Klasse.
Wir wollen, dass die situation eine Warnung und nicht ein Fehler weil es ein Fehler bedeutet, dass dies ist eine andere form der spröden base class problem. C# wurde sorgfältig entworfen, so dass, wenn jemand eine änderung an einer Basis-Klasse, die Auswirkungen auf den code, der verwendet eine abgeleitete Klasse minimiert werden.
Weil virtuelle überschreiben ist gefährlich. Virtuelle überschreiben erlaubt abgeleiteten Klassen ändern das Verhalten von code, der kompiliert wurde, um die Basisklassen verwenden. Etwas tun, gefährlich wie eine überschreibung sollte etwas sein, was Sie tun bewusst und bewusst, nicht durch Unfall.
Ich Stimme rückwärts Kompatibilität verletzen können. Mono hat beschlossen, drop-Unterstützung für die 1.1 in zukünftigen Versionen.
Brechen die Abwärtskompatibilität mit Ihrer Sprache ganz anders ist, als zu machen es einfach für Menschen, mit Ihrer Sprache zu brechen Abwärtskompatibilität mit Ihrem eigenen code. Erics Beispiel ist der 2. Fall. Und die person schriftlich, dass code, der eine Entscheidung getroffen hat, dass er will, dass die rückwärts-Kompatibilität. Die Sprache, die Sie unterstützen sollten, dass die Entscheidung, wenn möglich.
Gottes Antwort, Eric. Allerdings gibt es einen spezifischen Grund, warum das überschreiben standardmäßig ist schlecht. Wenn eine Basisklasse Base stellt eine neue Methode Ente() (liefert eine Ente-Objekt), die passiert haben die gleiche Signatur wie die bestehende Methode Ente() (das macht Mario Ente) in einer abgeleiteten Klasse Abgeleitet ist (D. H. keine Kommunikation zwischen Ihnen und dem Verfasser der Basis), Sie nicht wollen die Kunden der beiden Klassen, um Mario Ente, wenn Sie wollen einfach nur eine Ente.
In der Zusammenfassung, es hat meistens zu tun mit wechselnden Basis-Klassen und-Schnittstellen.
InformationsquelleAutor Eric Lippert
Wenn die Methode in der abgeleiteten Klasse vorangestellt ist das neue Stichwort, die Methode ist definiert als unabhängig von der Methode in der Basisklasse
Allerdings, wenn Sie nicht angeben, welche entweder neu oder überschreibt, die Ausgabe ist die gleiche, als wenn Sie angegeben neue, aber erhalten Sie eine compiler-Warnung (wie Sie vielleicht nicht bewusst sein, dass Sie versteckt sind, eine Methode in der Basisklasse die Methode, oder in der Tat können Sie haben wollte, um es zu überschreiben, und nur vergaß das Schlüsselwort).
Hilft Ihnen So, Fehler zu vermeiden und zeigen explizit, was Sie wollen zu tun und es macht mehr lesbaren code, so kann man leicht verstehen, den code.
InformationsquelleAutor Incognito
Es ist erwähnenswert, dass die nur Wirkung von
new
in diesem Zusammenhang ist zum unterdrücken einer Warnung. Es ist keine änderung in der Semantik.So eine Antwort ist: Wir brauchen
new
an-signal an den compiler, dass das Versteck ist absichtlich zu entledigen und die Warnung.Den follow-up-Frage ist: Wenn Sie nicht /können nicht eine Methode überschreiben, warum würden Sie die Einführung einer anderen Methode mit dem gleichen Namen? Da versteckt ist im wesentlichen ein name-Konflikt. Und Sie würden natürlich vermeiden es in den meisten Fällen.
Der einzige gute Grund, der mir einfällt für vorsätzliche versteckt ist, wenn ein name aufgezwungen wird Sie durch eine Schnittstelle.
InformationsquelleAutor Henk Holterman
In C# Mitglieder sind standardmäßig versiegelt was bedeutet, dass Sie nicht außer Kraft setzen können (sofern nicht anders gekennzeichnet-mit der
virtual
oderabstract
keywords) und dies aus performance-Gründen. Die neue modifier wird verwendet, um explizit ausblenden eines geerbten Mitglieds.Wenn Sie wollen explizit ausblenden ein Mitglied von einer Basisklasse geerbt wurden. Ausblenden eines geerbten Mitglieds bedeutet, dass die abgeleitete version von dem Mitglied ersetzt die Basis-Klasse-version.
Hinzugefügt auch Abstrakt 🙂
Aber alle Methoden, die die Basisklasse wird immer noch als die Basis-Implementierung, nicht abgeleitet werden. Dies scheint eine gefährliche situation für mich.
Dimitrov: ich habe auch eine harte Zeit, darüber nachzudenken, einen Anwendungsfall, in dem das neue Schlagwort wird wirklich gebraucht. Es scheint mir, dass es immer bessere Möglichkeiten. Ich Frage mich auch, ob versteckt eine Basis-Klasse, die Umsetzung ist nicht ein design-Fehler, die leicht zu einem Fehler führt.
InformationsquelleAutor Darin Dimitrov
Beim überschreiben war Standard, ohne Angabe der
override
Schlüsselwort, könnten Sie versehentlich überschreiben eine Methode, mit der Sie Ihre Basis nur aufgrund der Namensgleichheit..Net-compiler-Strategie ist, um Warnungen ausgeben, wenn etwas schief gehen könnte, nur um sicher zu sein, so dass in diesem Fall, wenn das überschreiben war Standard, es hätte eine Warnung sein für jede Methode überschrieben - so etwas wie "Warnung: überprüfen Sie, ob Sie wirklich überschreiben möchten'.
InformationsquelleAutor František Žiačik
Meine Vermutung würde sich vor allem durch die mehrfache interface-Vererbung. Mit diskreten Schnittstellen, es wäre sehr möglich, dass zwei verschiedene Schnittstellen verwenden die gleichen Signatur der Methode. Erlaubt die Verwendung der
new
keyword würde ermöglichen es Ihnen, erstellen Sie diese verschiedenen Implementierungen mit einer Klasse, anstatt zu erstellen, die zwei unterschiedliche Klassen.Aktualisiert ... Eric gab mir eine Idee, wie man an diesem Beispiel verbessern.
Die
new
Schlüsselwort können Sie auch ändern Sie die Vererbung Basis für alle Kinder aus.InformationsquelleAutor Matthew Whited
Wie bereits erwähnt, die Methode/Eigenschaft versteckt, die es möglich macht, Dinge zu ändern, etwa eine Methode oder eine Eigenschaft, die nicht leicht geändert sonst. Eine situation, in denen dies nützlich sein kann, ermöglicht es eine vererbte Klasse, Lesen-schreiben-Eigenschaften, die nur gelesen werden, die in der Basisklasse. Nehmen wir beispielsweise an, eine Basisklasse hat eine Reihe von nur-lese-Eigenschaften genannt Wert1-Value40 (natürlich einen echten Klasse verwenden würde besser den Namen). Eine versiegelte Nachkomme der diese Klasse hat einen Konstruktor, der ein Objekt der Basisklasse und kopiert die Werte aus, die Klasse wird nicht zulassen, dass Sie geändert werden, nachdem das. Eine unterschiedliche, vererbbare, Nachkomme deklarieren Sie eine Lesen-schreiben-Eigenschaften genannt Wert1-Value40 die, wenn Sie Lesen, verhält sich ähnlich wie der base-Klasse-Versionen aber, wenn geschrieben wird, können die Werte geschrieben werden. Der Netto-Effekt wird sein, dass code, der will, eine Instanz der Basis-Klasse, die es kennt, wird sich auch nie ändern können, erstellen Sie ein neues Objekt den nur-lese-Klasse, die das kopieren von Daten von einer übergebenen Objekt, ohne befürchten zu müssen, ob das Objekt nur Lesen oder Lesen /schreiben.
Einen ärger mit diesem Ansatz-vielleicht kann mir jemand helfen-ist, dass ich don ' T wissen, einen Weg, um sowohl Schatten und überschreiben einer bestimmten Eigenschaft innerhalb der selben Klasse. Mit einer der CLR-Sprachen zulassen, dass (ich benutze vb 2005)? Es wäre nützlich, wenn sich die Basisklasse-Objekt und seine Eigenschaften konnte Abstrakt sein, aber das würde erfordern, eine intermediate-Klasse zu überschreiben Wert1 Value40 Eigenschaften vor einer abgeleiteten Klasse könnte Schatten.
InformationsquelleAutor supercat
Sind Sie richtig, dass Sie das neue Schlüsselwort explizit verbirgt sich ein Mitglied von der Basis-Klasse, so dass die Anrufer am Ende mit dem Mitglied in Ihrer Unterklasse anstatt die superclass-version. Wie die blog-post erwähnt, können Sie implizit tun dies auch.
Anders als überschreiben einer Basisklasse member; zu tun, dass die Basis-Klasse Mitglied müssen gekennzeichnet werden als abstrakte oder virtuelle. Also nicht jedes Mitglied auf einer Basis-Klasse überschrieben werden können. Angenommen, Sie sind Unterklassen einer Klasse aus einem anderen assembly ist und Sie keinen Zugang haben, oder nicht wollen, gehen Sie zurück und Nachrüstung, von code, damit die Mitglieder virtuelle. Ohne das Schlüsselwort new, Sie würden geklebt werden.
Man kann sich streiten ob es besser ist, das keyword und explizit sein (meiner Meinung nach), oder tun Sie es einfach stillschweigend.
InformationsquelleAutor CodingGorilla