Gleichheit von Elementen in einer ArrayList
-
Hallo!
Zwei Instanzen einer Klasse, mit gleichen Werten initialisiert erkennt ArrayList nicht als gleich an ... warum ist t2 == false?
public class TestClass { private int _a; private int _b; public TestClass(int a, int b) { _a = a; _b = b; } } ArrayList arr = new ArrayList(); TestClass t1 = new TestClass(1, 1); TestClass t2 = new TestClass(1, 1); arr.Add(t1); bool test1 = arr.Contains(t1); // true bool test2 = arr.Contains(t2); // false
hat jemand eine Idee?
-
Weil zwar aus Deiner Sicht fachlich die beiden Klassen dieselben Inhalte enthalten, es sind aber physisch zwei unterschiedliche Klassen. t1 hat eine Referenz auf einen anderen Speicherbereich als t2. Somit sind die Referenzen nicht gleich. Du vergleichst mit Contains (bzw. ==) ja nur die Referenzen, nicht die Inhalte!
Woher sollte ArrayList.Contains auch ahnen, was Deine Klasse gleich/ungleich macht?Wenn Du die Inhalte abgleichen willst, mußt Du eine CompareTo Methode implementieren, die eben eine vorgegebene Klasse mit der aktuellen vergleicht. Du kannst dafür auch das Interface IComparable implementieren.
2x EDIT, ich bin noch nicht wirklich wach....
-
MSDN über CompareTo
Less than zero
This object is less than the other parameter.Zero
This object is equal to other.Greater than zero
This object is greater than other.Nun, bei TestClass gibt es kein größer oder kleiner! Desweiteren wird die Funktion TestClass.CompareTo beim einem ArrayList.Contains nicht mal aufgerufen ... habs ausprobiert ...
-
Contains ruft auch Equals und nicht CompareTo auf. Um nämlich zu prüfen ob ein Objekt vorhanden ist in einer Liste, reicht ein Vergleich auf Gleichheit. Equals musst du mit override überschreiben, dazu musst man dann auch immer GetHashCode überschreiben.
Und warum deines false ist hängt eben damit zusammen das du das Equals nicht überladen hast. Es wird dann das geerbte Equals aufgerufen und das vergleicht nur die Referenzen und die sind von deinen beiden Objekten eben nicht gleich.
Eine Überladung könnte so aussehen:
public override bool Equals(object obj) { TestClass x = obj as TestClass; if(x!=null) return _a.Equals(x.A) && _b.Equals(x.B); return false; // oder ne Exception }
Dazu solltest du noch Properties erstellen, damit du auch auf _a und _b von außen zugreifen kann.
In der MSDN gibt's hierzu auch einen Artikel:
http://msdn2.microsoft.com/en-us/ms182357.aspx
-
Jetzt funktionierts!
Danke!
Wegen der Properties bin ich schon wohl informiert
... war hier nur ein zusammengeschrupfter Beispielcode
Danke