0Pricing
C# Academy · Lektion

Gleichheit und Hashing (Wert und Referenz)

Verstehen Sie Referenz- und Wertgleichheit, überschreiben Sie Equals/GetHashCode korrekt, implementieren Sie IEquatable und verwenden Sie eigene Comparer mit Mengen und Dictionaries.

Gleichheit und Hashing (Wert und Referenz) ist eine kostenlose C# Academy-Lektion auf CoddyKit. Dies ist Lektion 3 von 3. Du kannst die komplette Lektion unten kostenlos lesen – dann übst du sie direkt im Browser mit einem integrierten Code-Editor und einem KI-Tutor rund um die Uhr. Sie ist Teil des C# Academy-Lernpfads, und dein Fortschritt wird über Web und CoddyKit-App synchronisiert. Der C# Academy-Kurs umfasst insgesamt 3 Lektionen.

Grundlagen der Gleichheit

Ziel: Sorgen Sie dafür, dass Gleichheitsvergleiche erwartungsgemäß funktionieren.

  • Referenz- vs. Wertgleichheit
  • Equals- und GetHashCode-Vertrag
  • IEquatable<T> für mehr Geschwindigkeit
  • Benutzerdefinierte Vergleicher, wenn Sie den Typ nicht ändern können

Stolperfalle bei der Referenzgleichheit

Klassen verwenden standardmäßig Referenzgleichheit. Zwei separate Objekte mit denselben Daten sind nicht gleich, sofern Sie keine Wertgleichheit implementieren.

using System;
using System.Collections.Generic;

public sealed class Point // no overrides
{
  public int X;
  public int Y;
  public Point(int x, int y){ X = x; Y = y; }
}

public class Program
{
  public static void Main(string[] args)
  {
    Point a = new Point(1, 2);
    Point b = new Point(1, 2);

    Console.WriteLine("a == b ? " + (a == b)); // reference equality: False
    Console.WriteLine("a.Equals(b) ? " + a.Equals(b)); // False

    HashSet<Point> set = new HashSet<Point>();
    set.Add(a);
    Console.WriteLine("Contains b? " + set.Contains(b)); // False (unexpected)
  }
}

Wertgleichheit implementiert

Implementieren Sie IEquatable<T> und überschreiben Sie Equals und GetHashCode. Der Hashwert muss mit der Gleichheit übereinstimmen: Gleiche Objekte → derselbe Hashwert.

using System;
using System.Collections.Generic;

public sealed class ValuePoint : IEquatable<ValuePoint>
{
  public int X;
  public int Y;
  public ValuePoint(int x, int y){ X = x; Y = y; }

  public bool Equals(ValuePoint other)
  {
    if (ReferenceEquals(other, null)) return false;
    if (ReferenceEquals(this, other)) return true;
    return X == other.X && Y == other.Y;
  }

  public override bool Equals(object obj)
  {
    return Equals(obj as ValuePoint);
  }

  public override int GetHashCode()
  {
    // Simple, stable combination (avoid randomness)
    unchecked
    {
      int hash = 17;
      hash = hash * 31 + X.GetHashCode();
      hash = hash * 31 + Y.GetHashCode();
      return hash;
    }
  }
}

public class Program
{
  public static void Main(string[] args)
  {
    ValuePoint a = new ValuePoint(1, 2);
    ValuePoint b = new ValuePoint(1, 2);

    Console.WriteLine("a.Equals(b)? " + a.Equals(b)); // True

    HashSet<ValuePoint> set = new HashSet<ValuePoint>();
    set.Add(a);
    Console.WriteLine("Contains b? " + set.Contains(b)); // True (value semantics)
  }
}

Benutzerdefinierter Vergleicher

Übergeben Sie einen benutzerdefinierten IEqualityComparer<T> an HashSet/Dictionary, wenn Sie den Typ selbst nicht ändern können.

using System;
using System.Collections.Generic;

public sealed class Person // imagine from a library; cannot edit
{
  public string Name;
  public int BirthYear;
  public Person(string name, int year){ Name = name; BirthYear = year; }
}

public sealed class PersonComparer : IEqualityComparer<Person>
{
  public bool Equals(Person a, Person b)
  {
    if (ReferenceEquals(a, b)) return true;
    if (ReferenceEquals(a, null) || ReferenceEquals(b, null)) return false;
    return a.Name == b.Name && a.BirthYear == b.BirthYear;
  }

  public int GetHashCode(Person p)
  {
    if (ReferenceEquals(p, null)) return 0;
    unchecked
    {
      int h = 23;
      h = h * 31 + (p.Name == null ? 0 : p.Name.GetHashCode());
      h = h * 31 + p.BirthYear.GetHashCode();
      return h;
    }
  }
}

public class Program
{
  public static void Main(string[] args)
  {
    Person p1 = new Person("Ada", 1815);
    Person p2 = new Person("Ada", 1815);

    HashSet<Person> set = new HashSet<Person>(new PersonComparer());
    set.Add(p1);
    Console.WriteLine("Contains p2? " + set.Contains(p2)); // True via comparer
  }
}

Vertrag und Stolperfallen

Regeln:

  • Wenn Equals(a,b) true ergibt ⇒ GetHashCode(a) == GetHashCode(b)
  • Die Gleichheit sollte reflexiv, symmetrisch und transitiv sein
  • Verwenden Sie nach Möglichkeit unveränderliche Felder für das Hashing
  • Verwenden Sie in GetHashCode keine Zufallswerte

Hinweis zu Structs und Klassen

Structs werden standardmäßig anhand ihrer Felder verglichen (Wertsemantik). Klassen werden standardmäßig anhand ihrer Referenz verglichen, sofern Sie keine Wertgleichheit implementieren.

using System;

public struct PointS // struct: value type
{
  public int X;
  public int Y;
  public PointS(int x, int y){ X = x; Y = y; }
}

public class Program
{
  public static void Main(string[] args)
  {
    PointS a = new PointS(1, 2);
    PointS b = new PointS(1, 2);
    Console.WriteLine("Struct equality: " + a.Equals(b)); // True by default (field-wise)
  }
}

Gleichheitsvertrag für Collections

Schnelltest: Um einer Klasse Wertgleichheit zu geben, die in HashSet und Dictionary funktioniert, was sollten Sie implementieren?

Zusammenfassung

Zusammenfassung: Klassen benötigen Equals/GetHashCode (und häufig IEquatable<T>) für Wertsemantik. Verwenden Sie benutzerdefinierte Vergleicher, wenn Typen nicht bearbeitet werden können.

Häufig gestellte Fragen

Ist die Lektion „Gleichheit und Hashing (Wert und Referenz)“ kostenlos?

Ja — der vollständige Text von „Gleichheit und Hashing (Wert und Referenz)“ ist hier im Web kostenlos zu lesen. Um sie interaktiv zu üben (integrierter Code-Editor und 24/7 KI-Tutor) und den Rest des C# Academy-Kurses freizuschalten, upgrade auf CoddyKit PRO. Der C# Academy-Kurs umfasst insgesamt 3 Lektionen.

Was lerne ich in „Gleichheit und Hashing (Wert und Referenz)“?

Verstehen Sie Referenz- und Wertgleichheit, überschreiben Sie Equals/GetHashCode korrekt, implementieren Sie IEquatable und verwenden Sie eigene Comparer mit Mengen und Dictionaries. Du übst C# Academy mit praktischem Code, den du direkt im Browser ausführst, und ein 24/7 KI-Tutor beantwortet deine Fragen während du die Lektion bearbeitest.

Brauche ich Erfahrung, um C# Academy zu starten?

Keine Vorkenntnisse erforderlich. C# Academy auf CoddyKit ist für Anfänger bis fortgeschrittene Lernende strukturiert, sodass du hier starten oder von Anfang an beginnen und in deinem eigenen Tempo voranschreiten kannst. Dies ist Lektion 3 von 3.

Wie lange dauert die Lektion „Gleichheit und Hashing (Wert und Referenz)“?

Die meisten CoddyKit-Lektionen dauern etwa 5–10 Minuten. Jede ist kompakt und interaktiv, sodass du stetig Fortschritte machst und genau dort weitermachst, wo du aufgehört hast – im Web und in der App.

Kann ich in dieser C# Academy-Lektion Code schreiben und ausführen?

Ja. Jede C# Academy-Lektion enthält einen integrierten Code-Editor, sodass du echten Code direkt in deinem Browser schreibst und ausführst und sofort KI-Feedback erhältst — ohne lokale Einrichtung erforderlich.

Alle Lektionen in diesem Kurs

  1. HashSet , SortedSet , Queue , Stack
  2. ConcurrentDictionary und unveränderliche Sammlungen
  3. Gleichheit und Hashing (Wert und Referenz)
← Zurück zu C# Academy