Laden...

Equals und GetHashCode

Erstellt von leb0rtran vor 13 Jahren Letzter Beitrag vor 13 Jahren 2.179 Views
L
leb0rtran Themenstarter:in
26 Beiträge seit 2008
vor 13 Jahren
Equals und GetHashCode

hi,

hab n paar Fragen zu Equals und GetHashCode:

hier erstmal ne Beispielklasse:


class BspCLass
{
  public int ID = 0;
  public String Value = null;

  public BspClass(String v)
  {
    this.Value = v;
  }

  public override string ToString()
  {
    return this.Value;
  }

  public override bool Equals(object obj)
  {
    if (obj == null || !(obj is BspCLass))
      return false;

    return this.ID == ((BspCLass)obj).ID;
  }

  public override int GetHashCode()
  {
    return base.GetHashCode() + (int)this.ID;
  }
}

so in etwa sehen meine Klassen aus (die dann in ner Datenbank gespeichert werden, im programm selber wird dann immer mit den Klassen gearbeitet, nicht mit den DataRows.

Was atm funktioniert is, wenn ich ein Objekt 2 mal aus der Datenbank hole (hat dann immer die selbe ID, zB 5, wenn ID 0 ist, bedeutet das, dass das Objekt noch nicht in der DB vorkommt) und beide vergleiche kommt true raus, dan Equals.

Aber, sind beide Objekte jetzt auch ander selben stelle im Speicher, bzw zeigt die Referenz an die selbe Speicherstelle?
Das müsste ja durch GetHashCode geregelt werden, wenn cih das richtig verstanden hab?

Die Idee für die Hashfunktion hab ich iwo im Netz gefunden, kann mir aber kaum vorstellen, dass die funktioniert, also für 2 Objekte mit der selben ID immer den selben code bringt, base.GetHashCode() ja verschieden sein könnte, oder?
nur die ID als HashCode zu nemen is ja auch nich optimal, da 2 Objekte verschiedener Klassen mit selber ID ja an verschiedenen Speicherplätzen sein sollem/müssen

Wäre super wenn mir da jemand weiterhelfen könnte

mfg

C
401 Beiträge seit 2007
vor 13 Jahren

Hi,

der Hashcode zweier Objekte mit gleichen Werten ist auch immer gleich. Allerdings lässt ein Hashcode niemals auf Gleichheit zweier Objekte schließen. Nur wenn 2 Hascodes unterschiedlich sind kann man sicher sein, dass die Objekte nicht gleich sind. Der Hashcode sollte also so zusammengebaut werden, dass er konsistente Ergebnisse liefert. Also für Objekte mit gleichem Wert auch immer den gleichen Hashcode. Aber wie gesagt... auf die wirkliche Gleichheit muss man schon selber prüfen.

849 Beiträge seit 2006
vor 13 Jahren

Hallo Corpsegrinder, lass mal folgenden Code Laufen.. Du wirst sehen das Objekte auch mit gleichen Werten verschiedene Hashcodes haben.

Dieses kann nur mit der Implementierung von GetHashcode umgangen werden.

Und nein, wenn zwei Objecte den selben Hashcode liefern, heisst das nicht das sie auf den selben Speicher verweisen.


static void Main(string[] args)
        {
            Console.WriteLine(new Test { TestString = "Test" }.GetHashCode());
            Console.WriteLine(new Test { TestString = "Test" }.GetHashCode());
            Console.ReadLine();
        }

        public class Test
        {
            public string TestString { get; set; }
        }  

C
401 Beiträge seit 2007
vor 13 Jahren

Entschuldigung, da habe ich mich wohl etwas falsch ausgedrückt... Sie "sollten" den gleichen Hashcode liefern. Aber es ist ja klar, dass der Hashcode von Object nicht anhand der Properties entscheiden kann, welchen Hashcode er liefert, ansonsten müsste man sich ja keine Gedanken darüber machen. Ich dachte das wäre soweit klar.

6.910 Beiträge seit 2009
vor 13 Jahren

Hallo,

siehe auch Klasse mit Checksum versehen. Möglich?. Da wird eine Tücke erklärt die zu berücksichtigen ist.

mfG Gü

Stellt fachliche Fragen bitte im Forum, damit von den Antworten alle profitieren. Daher beantworte ich solche Fragen nicht per PM.

"Alle sagten, das geht nicht! Dann kam einer, der wusste das nicht - und hat's gemacht!"

49.485 Beiträge seit 2005
vor 13 Jahren

Hallo leb0rtran,

ob die Referenzen gleich sind, also ob es sich um dasselbe Objekt handelt, spielt hier doch gar keine Rolle. Wenn ich dich richtig verstanden habe, kommt es für die Gleichheit nur auf die ID an. Zumindest ist dein Equals so implementiert. GetHashCode muss immer passend zu Equals implementiert sein. Vor allem die Forderung

Wenn zwei Objekte desselben Typs denselben Wert darstellen, muss die Hashfunktion für beide Objekte denselben konstanten Wert zurückgeben.

muss man in diesem Zusammengang erfüllen. Korrekt wäre also z.B.

public override int GetHashCode() {
    return (int)this.ID;
}

Und was anderes wird dir wohl auch kaum übrig bleiben.

herbivore

3.170 Beiträge seit 2006
vor 13 Jahren

Hallo unconnected,

Du wirst sehen das Objekte auch mit gleichen Werten verschiedene Hashcodes haben.

In Deinem Beispiel packst Du den Wert ja in eine Klasse, und instanziert diese mehrfach. Der Wert spielt dann für GetHashCode ja gar keine Rolle, und Equals wird für diese Objekte auch nicht true liefern, da es nicht überschrieben ist.
Ich denke Corpsegrinder meinte mit "gleiche Werte", daß eine Gleichheitsprüfung true ergibt.

Gruß, MarsStein

Non quia difficilia sunt, non audemus, sed quia non audemus, difficilia sunt! - Seneca