Probleme mit überladenem operator ==
-
man, ist das durcheinander. wieso schreiben wir denn alle gleichzeitig. Naja,
@andreas
aber wie mache ich denn dann? Das leuchtet mir schon ein, dass das gefährlich ist.
-
also,
CollisionMaterial temp=(CollisionMaterial) o; if(temp !=null) return id == temp.Id; else return false;
funktioniert auch nicht. Zudem benutze ich dann ja den != operator, den ich ebenfalls überschreibe und welcher auch mit Equals prüft.
-
Was klappt an meiner Methode nicht? Du willst doch anhand der id feststellen, ob zwei Objekte gleich sind, oder?
(Was übrigens keine gute Vorgehensweise ist. Equals sollte nicht prüfen, ob das die selben beiden Objekte sind, sondern ob sie logisch gleich sind. Ich gehe mal davon aus, dass es jede id nur einmal gibt.)
Wenn du wirklich prüfen willst, ob es die absolut selben Objekte sind, warum vergleichst du dann nicht die Referenzen einfach?
-
Hi,
Debuggen == programmieren
public override bool Equals(object o) { CollisionMaterial temp=(CollisionMaterial) o; if(temp !=null) return id == temp.Id; else return false; } public static bool operator ==(CollisionMaterial m1, CollisionMaterial m2) { CollisionMaterial temp=(CollisionMaterial) o; if(temp !=null) // setze hier mal einen Haltepunkt. und stepp dann langsam duch. Schuen im Fenster "local" die Zustände der lokalen Variablen an return m1.Equals(m2); else return m2==null; }
-
Frei nach Andreas' Motto "selbst ist der Mann" habe ich gerade die Lösung gefunden:
Das Problem lag nämlich in der Tat darin, dass beim Aufruf if(mat == null) natürlich mat wirklich null ist. Und dann knallt es im operator ==.
Ergo: vorher testen, ob m1 null ist. Sieht zwar jetzt nicht schön aus, klappt aber.public override bool Equals(object o) { if(o == null) return false; CollisionMaterial tmp = (CollisionMaterial) o; return id == tmp.Id; } public static bool operator ==(CollisionMaterial m1, CollisionMaterial m2) { if(((object)m1) == null) { if(((object) m2) == null) return true; return false; } return m1.Equals(m2); } public static bool operator !=(CollisionMaterial m1, CollisionMaterial m2) { if(((object)m1) == null) { if(((object) m2) == null) return false; return true; } return !m1.Equals(m2); }
-
übrigens: gefunden durch das Verwenden von Haltepunkten
-
hehe,
in euIRC #net wäre es einfacher, wenn man eh in Chat-Tempo postet
-
if(((object)m1) == null)
Das ist völlig Schwachsinn. Und warum benutzt du nicht den Operator as, mit dem sich das um einiges schöner schreiben lässt?
Und schau dir auch mal an, was ein Equals machen sollte:
http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Object.html#equals(java.lang.Object)
Ist zwar Java, aber das hat C# eh von Java geklaut.
-
das stimt vielleicht
Naja, vielen Dank auf jeden Fall. Meint ihr, dass es noch einfacher geht?
-
Optimizer schrieb:
Und schau dir auch mal an, was ein Equals machen sollte:
http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Object.html#equals(java.lang.Object)
Ist zwar Java, aber das hat C# eh von Java geklaut.das ist doch gewährleistet.
-
Hm, die Datenbank war gerade weg, aber jetzt kann es ja weiter gehen.
- mit Java habe ich kein Problem -- da komme ich eigentlich her. Ich denke auch, dass meine Implementierung alles erfüllt. Allerdings habe ich auch auf den Optimizer gehört und sie wie folgt geändert. Damit fange ich den Fall ab, dass Objekte anderer Klassen übergeben werden:
public override bool Equals(object o) { CollisionMaterial tmp = o as CollisionMaterial; if(tmp == null) return false; return id == tmp.Id; }
- if(((object)m1) == null) ist NICHT schwachsinn. Ich muss uzm object casten, da ich sonst immer den überladenen operator aufrufe und so einen Stack-Overfow bekomme...
-
Stimmt, daran habe ich nicht gedacht. Aber hast du es schonmal mit Object.operator== oder base.operator== probiert? Dann würdest du dir den cast sparen (ich hasse casts).
Ist jetzt ungetestet, aber solltest du vielleicht mal kurz noch checken.
-
AndreasW schrieb:
Optimizer schrieb:
Und schau dir auch mal an, was ein Equals machen sollte:
http://java.sun.com/j2se/1.4.2/docs/api/java/lang/Object.html#equals(java.lang.Object)
Ist zwar Java, aber das hat C# eh von Java geklaut.das ist doch gewährleistet.
Sicher? Eine id zu vergleichen bedeutet für mich Referenzgleichheit. Dazu sollte man Equals() nicht verwenden, und man kann sich das überladen von == dann auch sparen.
Falls mehrere Objekte die selbe id haben können, bitte ich um Verzeihung.
-
Also, ich lese die CollisionMaterials aus einer Xml-Datei aus. Andere Objekte referenzieren ("benutzen") jeweils ein CollisionMaterial über dessen Id. In der Liste, welche die Materials speichert, möchte ich keine doppelten Objekte haben.
Aber Equals (und operatoren) zu überschreiben, ist doch gerade der Sinn des Ganzen. Wenn ich Objekte auf eine bestimmte Art und Weise vergleiche / identifiziere, kann das so gewährleisten.
Das ist doch das gleiche Prinzip, wie Javas Interface Comparable (mit der Methode public boolean CompareTo(Object o)), nur eleganter, weil ich in C# die Operatoren überladen kann und sie dann benutzen kann, wie bei ganz normalen. primitiven Datentypen bzw. String.
-
Nein, das hat mit Compareable nicht zu tun.
Equals() - Ob zwei (möglicherweise nicht die selben) Objekte den gleichen Zustand haben. Bsp.: Zwei verschiedene Brüche, die den selben Wert haben
=> logische GleichheitEquals ist nicht dafür gedacht, zu prüfen, ob zwei Objekte die selben sind. Dazu brauchst du sowieso nur die Referenz vergleichen, da kannst du dir den ganzen Aufwand sparen.
Weise vergleiche / identifiziere
Vergleichen ja, identifizieren nein!
Du kannst natürlich machen, was du willst. Aber deine Klasse möchte ich dann nicht im nächsten Framework haben.
-
edit: war egal
edit: oder vielelicht doch:Equals() - Ob zwei (möglicherweise nicht die selben) Objekte den gleichen Zustand haben. Bsp.: Zwei verschiedene Brüche, die den selben Wert haben
=> logische Gleichheitja. Beispiel aus der Hilfe:
using System; public class MyClass { public static void Main() { string s1 = "Tom"; string s2 = "Carol"; Console.WriteLine("Object.Equals(\"{0}\", \"{1}\") => {2}", s1, s2, Object.Equals(s1, s2)); s1 = "Tom"; s2 = "Tom"; Console.WriteLine("Object.Equals(\"{0}\", \"{1}\") => {2}", s1, s2, Object.Equals(s1, s2)); s1 = null; s2 = "Tom"; Console.WriteLine("Object.Equals(null, \"{1}\") => {2}", s1, s2, Object.Equals(s1, s2)); s1 = "Carol"; s2 = null; Console.WriteLine("Object.Equals(\"{0}\", null) => {2}", s1, s2, Object.Equals(s1, s2)); s1 = null; s2 = null; Console.WriteLine("Object.Equals(null, null) => {2}", s1, s2, Object.Equals(s1, s2)); } } /* This code produces the following output. Object.Equals("Tom", "Carol") => False Object.Equals("Tom", "Tom") => True Object.Equals(null, "Tom") => False Object.Equals("Carol", null) => False Object.Equals(null, null) => True */
Es wird überprüft, ob der Wert eines Objektes gleich ist.
Du kannst natürlich machen, was du willst. Aber deine Klasse möchte ich dann nicht im nächsten Framework haben.
dann würd ich das .NET Framework an deiner stelle nicht benutzen. Das wird nämlich überall gemacht.
Du sagst doch selber: "Equals() - Ob zwei (möglicherweise nicht die selben) Objekte den gleichen Zustand haben.". Dass prüft er ja, indem er die ID vergleicht.
Somit macht genau dass, was Equals machen soll (solange die ID eindeutig ist).
-
hmm. aber mache ich denn nicht genau das? Die Objekte vergleichen (egal, ob mit == oder Equal) und anhand des Merkmals Id entscheiden, ob sie es nun sind oder nicht?
Ach übrigens, Id ist genau sowas, wie bei einer Klasse "Konto" die Werte BLZ und KontoNr zusammen. Also die eindeutige Enterscheidung. Ist das dann nicht korrekt?
Ich möchte gerne darüber diskutieren, denn ich bin offen für Kritik / Rat, da ich schon sauber programmieren möchte.
-
Betrag editiert. Ich wollt mirs erst verkneifen Das edititeren hab aber recht lange gedauert, dashalb die verzögerung. Das Forum spinnt mal wieder
-
Equals() - Ob zwei (möglicherweise nicht die selben) Objekte den gleichen Zustand haben. Bsp.: Zwei verschiedene Brüche, die den selben Wert haben
=> logische GleichheitOk, was macht dann der == Operator? ist der gleichzusetzen mit Equal? Soll der die Referenzen prüfen?
Ich kann ja nochmal schreiben, worum es mir geht:
Ich habe Objekte des Typ CollisionMaterial in einer Liste. Ich möchte vermeiden, dass ich die gleichen Objekte mehrmals in die Liste packe. Dafür reicht aber nicht ein list.Contains (welches wohl die Referenzen prüft). Denn die Objekte können durchaus verschieden sein. Wenn sie aber die gleiche Id haben, möchte ich das zweite Objekt NICHT in die Liste packen, sondern es verwerfen.
-
Glaub mir, ich weiss, wie Equals() im Framework verwendet wird.
Du sagst doch selber: "Equals() - Ob zwei (möglicherweise nicht die selben) Objekte den gleichen Zustand haben.". Dass prüft er ja, indem er die ID vergleicht.
Genau die ID ist das, was er nicht vergleichen soll. Wenn du z.B. Autos mit Equals() vergleichst, musst du vergleichen, ob sie die selbe Farbe haben, die selbe Automarke, die selben Extras und nicht ob es die selben sind.
Somit macht genau dass, was Equals machen soll (solange die ID eindeutig ist).
Genau dann eben nicht. Wenn die ID eindeutig ist, dann macht es nämlich nicht das, was Equals machen soll, weil es nur true liefert, wenn es die selben Objekte sind.
Wenn er jetzt zwei CollisionMaterials hat, die genau den gleichen Inhalt haben, liefert sein Equals() false, außer es sind wirklich die selben Objekte. Equals soll aber true liefern, wenn zwei Objekte logisch gleich sind.Bitte denk doch mal kurz darüber nach: Equals soll Objektgleichheit feststellen und nicht Objektidentität. Anders wäre es auch Bullshit, denn dafür müsste er nur die Referenzen vergleichen.
Dir ist doch der Unterschied zwischen Objektgleichheit und Objektidentität klar?Jetzt überleg: Er vergleicht eindeutig IDs, das heisst er könnte auch gleich die Referenzen vergleichen. Ist es wirklich das, was Equals machen soll?