Guten Abend,
ich möchte den == Operator zum überprüfen der Wertgleichheit von 2 Objekten prüfen.
Auf Richtlinien zum Überschreiben von Equals() und des Operators == steht:
Standardmäßig prüft der Operator == auf Verweisgleichheit, indem er ermittelt, ob zwei Verweise dasselbe Objekt angeben. Deshalb müssen Referenztypen keinen Operator == implementieren, um diese Funktionalität zu erhalten. Wenn ein Typ unveränderlich ist, d. h., wenn die in der Instanz enthaltenen Daten nicht geändert werden können, kann ein Überladen des Operators == zum Prüfen der Wertgleichheit statt der Verweisgleichheit nützlich sein. Der Grund dafür ist, dass bei unveränderlichen Objekten davon ausgegangen werden kann, dass sie identisch sind, wenn sie identische Werte haben. Es wird davon abgeraten, den Operator == in nicht unveränderlichen Typen zu überschreiben.
Ich versteh es nicht. Warum wird davon abgeraten? Ich möchte den == Operator überschreiben weil == einfacher zu lesen ist als *.Equals(...).
Ich bedanke mich schonmal!
Hallo dahaack,
willkommen bei myCSharp.de
Kurz gesagt vergleicht der == Operator ob es die gleichen Objekte sind.
D.h. Ob der Verweis auf ein und das selbe Objekt geht.
Dabei werden die Werte des Objekts nicht verglichen, es wird nur auf den Verweis geschaut.
Da das in der Regel für die meisten (veränderbaren) Datentypen genau das selbe ist braucht man es nicht zu überschreiben
Beim Equals hingegen werden normalerweise die einzelnen Properties gegeneinander abgeprüft.
Damit kannst du dann feststellen ob zwei Objekte den selben Inhalt haben.
Und wenn du dir selbst deine Objekte machst, dann musst du es halt überschreiben um deine eigene Equals-Funktion zu haben
Also kurz gesagt == vergleicht nur den Verweis (außer bei unveränderlichen Typen) und Equals vergleicht normalerweise den Inhalt (man kann es aber auch auf andere Art und weiße implementieren, was aber nicht empfehlenswert ist =)
Gruß
Michael
Hallo dahaack,
dem kann ich nicht zustimmen. operator== und Equals sollten immer konsistent zueinander implementiert sein. Bezogen auf eine bestimmte Klasse, sollten also entweder beide die Referenz vergleichen oder beiden den Wert/Inhalt!
Wenn man bei Objekten, bei denen von operator== und Equals ein Wertvergleich durchgeführt wird, aus bestimmten Gründen die Referenzgleicheit prüfen will, kann man Object.ReferenceEquals verwenden.
Hallo dahaack,
die Beschreibung in der MSDN hebt leider auf das falsche Kriterium ab. Nicht die Änderbarkeit des Objekts ist das entscheidende, sondern ob es sich konzeptuell um einen Referenztyp oder einen Werttyp handelt. Bei ersten braucht und sollte man deshalb weder Equals noch operator== überschreiben (mit dem Überschreiben von operator== ist es sowieso so eine Sache, weil das ja keine virtuelle Methode ist, dazu gleich mehr). Wenn man jedoch konzeptuell einen Werttyp hat, sollte man in der Regel Equals und operator== zueinander konsistent überschreiben.
Normalerweise wird man Typen, die konzeptuell Referenztypen sind, auch als technisch als Referenztypen (class) implementieren und Typen, die die konzeptuell Werttypen sind, auch als technisch als Werttypen (struct) implementieren (es gibt aber auch Ausnahmen, siehe [FAQ] Besonderheiten der String-Klasse (immutabler Referenztyp mit Wertsemantik)).
Meistens wird mal also Equals und operator== nur bei structs implementieren. Da man von structs nicht erben kann, gibt es auch kein Problem damit, dass operator== eine statische Methode ist. Wenn man aber ausnahmsweise einen konzeptuellen Werttyp als class implementiert und entsprechend Equals und operator== überschreibt (wie das bei der schon genannten String-Klasse der Fall ist), sollte man operator== unbedingt intern per Equals implementieren (oder die Klasse final machen)!
Wenn man das nicht täte, gäbe ein Problem, wenn der in class A definierte operator== später mit Variablen vom Typ A als Parameter aufgerufen wird, in denn zur Laufzeit aber Objekte der Unterklasse B stecken. Wie man sich leicht überlegen kann, würde operator== sonst die Objekte vom Typ B so vergleichen als wären Sie (nur) vom Typ A und somit inbesondere zusätzliche Felder in B beim Vergleich ignorieren.
Der Kreis zu der MSDN schließt sich dadurch halbwegs wieder, dass man konzeptuelle Werttypen, die man aus bestimmten Gründen per class implementiert, meistens als immutable implementieren wird (also das, was die MSDN unveränderlichen Typ nennt).
herbivore
Suchhilfe: 1000 Worte
Hallo,
vielen Dank an Euch!
Da das in der Regel für die meisten (veränderbaren) Datentypen genau das selbe ist braucht man es nicht zu überschreiben
Dies ist bei mir nicht der Fall. Ich habe 2 separate Objekte, die auf Wertgleichheit überprüft werden sollen.
Beim Equals hingegen werden normalerweise die einzelnen Properties gegeneinander abgeprüft.
Ich versteh nicht ganz, warum C# es so kompliziert gemacht hat, dass man das noch selbst überschreiben muss... Was passiert in einer nicht überschriebenen Equals Funktion?
Normalerweise wird man Typen, die konzeptuell Referenztypen sind, auch als technisch als Referenztypen (class) implementieren und Typen, die die konzeptuell Werttypen sind, auch als technisch als Werttypen (struct) implementieren
Bevor ich deine weitere Antwort verstehen kann muss ich erstmal wissen was du mit konzeptueller Wert-/Referenztyp meinst. Google findet für ""konzeptueller werttyp" c#" kein Suchergebnis. 😉
Vielen Dank nochmal!
Hallo dahaack,
Ich versteh nicht ganz, warum C# es so kompliziert gemacht hat, dass man das noch selbst überschreiben muss...
das hättest du aus dem bereits Gesagten aber leicht erschließen können: Da Operatoren statische Methoden sind, braucht man noch eine virtuelle Variante und das ist eben Equals.
Was passiert in einer nicht überschriebenen Equals Funktion?
Die Methoden des .NET Frameworks verwenden intern in der Regel Equals und würden dann bei deiner Klasse auf die Nase fallen. Jeder Benutzer deiner Klasse kann außerdem auf die Nase fallen. Equals und operator== sollen (ich kann auch sagen müssen) immer konsistent zueinander implementiert sein. Am einfachsten kann man das sicherstellen, indem man die eigentliche Vergleichslogik in Equals packt und operator== unter Verwendung von Equals implementiert.
was du mit konzeptueller Wert-/Referenztyp meinst.
Naja, eben ob es sich auf Ebene des Konzept - also bevor es um die Implementierung geht - um einen Werttyp handelt. Es kann ja Gründe geben, warum man eine Klasse, die konzeptionell ein Werttyp ist, technisch mit einem anderen Mittel implementiert, so wie das bei String der Fall ist. Inhaltlich/gedanklich/konzeptuell ist das ein Werttyp, aber technisch implementiert ist es über einen Referenztyp (class). Weil es diese Abweichung geben kann muss man zwischen Konzept und Implementierung unterscheiden.
herbivore
Hallo herbivore,
vielen Dank!
Was passiert in einer nicht überschriebenen Equals Funktion?
Die Methoden des .NET Frameworks verwenden intern in der Regel Equals und würden dann bei deiner Klasse auf die Nase fallen.
Du meinst die Klassen des .NET Frameworks? Entweder versteh ich die Antwort nicht oder sie beantwortet meine Frage nicht. 😉
Meine Frage war, wie die interne virtuelle Equalsmethode der Klasse System.Object implementiert ist, ob diese einfach nur die Adresse der beiden Objekte vergleicht?
Naja, eben ob es sich auf Ebene des Konzept - also bevor es um die Implementierung geht - um einen Werttyp handelt.
Hmm, tut mir leid ich versteh es noch nicht. Meinst du mit:
Konzeptioneller Referenztyp: Ein Typ der bei einer Vergleichsmethode die Referenz vergleicht.
Konzeptioneller Werttyp: Ein Typ der bei einer Vergleichsmothode die Werte vergleicht.
?
Hallo dahaack,
Meine Frage war, wie die interne virtuelle Equalsmethode der Klasse System.Object implementiert ist, ob diese einfach nur die Adresse der beiden Objekte vergleicht?
schau sowas bitte immer selbst in der :rtfm: Doku nach.
Hmm, tut mir leid ich versteh es noch nicht.
Ich verstehe ehrlich gesagt, was daran nicht zu verstehen ist. Ich habs mehrfach klar erklärt. Möglicherweise machst du vor dem Programmieren kein Konzept bzw. Entwurf. Dann ist es natürlich schwer zu verstehen. Du klebst offenbar zu sehr an den Programmiersprache. Eine Zahl ist (konzeptionell) typischerweise ein Werttyp, eine Person ist (konzeptionell) typischerweise ein Referenztyp, ganz egal ob oder in welcher Programmiersprache des später vielleicht mal umgesetzt wird oder ob diese Programmiersprache diese Unterscheidung überhaupt kennt.
herbivore
schau sowas bitte immer selbst in der :rtfm: Doku nach.
Oder direkt im Reflector.
Weeks of programming can save you hours of planning
Hallo,
nochmal vielen Dank für die Hilfe. Bin ein C# Quereinsteiger und tu mich deshalb mit einigem noch ein bisschen schwer.
Danke an Euch!