20% off with code ERSTIS26
5 min read 07 Aug 2026

C# ToString Equals GetHashCode: Object-Methoden erklärt

Die Object-Klasse in C# liefert essenzielle Methoden. Verstehe ToString, Equals & GetHashCode – wichtig für Azubis, Studenten & Berufseinsteiger.

Marcel Schmidtpeter By Marcel Schmidtpeter 07 Aug 2026

Stell dir vor, du debuggst eine Liste von `Person`-Objekten und in der Ausgabe steht nur `Person` mit irgendwelchen kryptischen Zahlen. Du fragst dich: "Warum zeigt der mir nicht einfach den Namen an?" Genau hier kommen die drei Methoden aus der `Object`-Klasse ins Spiel: `ToString`, `Equals` und `GetHashCode`.

In C# erbt jede Klasse - ob du willst oder nicht - von der Basisklasse `Object`. Das gilt für deine eigenen Klassen genauso wie für eingebaute Typen wie `string` oder `int`. Diese Vererbung bringt Methoden mit, die das Standardverhalten deiner Objekte steuern. Sie bestimmen, wie Objekte als Text dargestellt werden, wann sie als "gleich" gelten und welcher Hash-Wert sie haben.

Wenn du diese Methoden nicht überschreibst, liefert C# nur die Standardimplementierung. Die Beschäftigung mit dem Thema C# ToString Equals GetHashCode lohnt sich extrem, weil dir die Standardvorgaben im Alltag oft nicht weiterhelfen.

Ob du dich auf die IHK-Prüfung vorbereitest, im Studium OOP-Grundlagen nachholst oder im ersten Job auf Legacy-Code triffst: Irgendwann musst du verstehen, was diese Methoden machen. Hier ist die praxisnahe Erklärung.

Was ist ToString() und wann überschreibt man sie?

Die Methode `ToString()` gibt eine textuelle Repräsentation deines Objekts zurück. Der Standard liefert einfach den vollqualifizierten Klassennamen - also Namespace und Typname. Das ist beim Debuggen genauso wenig hilfreich wie in der UI-Anzeige.

Stell dir vor, du hast eine Klasse `Auto`. Ohne Überschreibung liefert `ToString()` nur `MeinNamespace.Auto`. Überschreibst du die Methode, kannst du stattdessen Marke, Modell und Baujahr zurückgeben. Dann macht ein `Console.WriteLine(meinAuto)` genau das, was du erwartest.

Merke: `ToString()` wird automatisch aufgerufen, wenn du ein Objekt in einem String-Kontext verwendest - z.B. bei String-Interpolation, `Console.WriteLine` oder beim Logging.

Hier ist ein einfaches Beispiel:

csharp
public class Auto
{
  public string Marke { get; set; }
  public string Modell { get; set; }
  public int Baujahr { get; set; }

  public override string ToString()
  {
    return $"{Marke} {Modell} ({Baujahr})";
  }
}

// Verwendung
Auto meinAuto = new Auto { Marke = "Volkswagen", Modell = "Golf", Baujahr = 2020 };
Console.WriteLine(meinAuto);  // Ausgabe: Volkswagen Golf (2020)

Die offizielle Dokumentation dazu findest du bei Microsoft Learn - Object.ToString-Methode.

Was ist Equals() und wie vergleicht man Objekte richtig?

`Equals()` prüft, ob zwei Objekte inhaltlich gleich sind. Das Problem: Standardmäßig vergleicht C# bei Referenztypen nur die Referenz - also die Speicheradresse. Zwei verschiedene `Auto`-Objekte mit identischen Werten gelten erst einmal als ungleich, weil sie an unterschiedlichen Orten im Speicher liegen.

Stell dir zwei Zettel vor, auf denen exakt dasselbe steht. Inhaltlich sind sie identisch, aber es sind trotzdem zwei verschiedene Blätter Papier. Genau so funktioniert der Standardvergleich bei Referenztypen.

csharp
public override bool Equals(object obj)
{
  if (obj == null || GetType() != obj.GetType())
  {
    return false;
  }

  Auto anderes = (Auto)obj;
  return Marke == anderes.Marke &&
          Modell == anderes.Modell &&
          Baujahr == anderes.Baujahr;
}

Warum die ganze Arbeit? Weil du sonst bei Collections wie `List<T>.Contains()` oder bei LINQ-Abfragen falsche Ergebnisse bekommst. Ohne Überschreibung sucht C# nach dem exakt selben Objekt im Speicher - nicht nach einem inhaltlich gleichen Duplikat.

Es gibt zwei Varianten, die du kennen solltest:

Methode

Beschreibung

Beispiel

`Equals(object obj)`

Standardmethode, überschreibbar

Vergleich mit `object` als Parametertyp

`Equals(T other)`

Typsichere Variante via `IEquatable<T>`

Direkter Vergleich ohne umständliches Casten

Merke: Wenn du `Equals()` überschreibst, musst du auch `GetHashCode()` überschreiben. Sonst brechen Hash-basierte Collections wie `Dictionary` oder `HashSet`.

Details dazu liefert Microsoft Learn - Object.Equals-Methode.

Was ist GetHashCode() und warum ist sie wichtig?

`GetHashCode()` liefert einen numerischen Wert - den Hash-Wert - der ein Objekt für Hash-basierte Datenstrukturen identifiziert. Diese Methode ist essenziell für `Dictionary<TKey, TValue>`, `HashSet<T>` und andere Collections, die intern Hash-Tabellen verwenden.

Der Hash-Wert funktioniert wie ein Postleitzahlen-System: C# nutzt ihn, um Objekte extrem schnell in "Fächer" einzusortieren. Wenn zwei Objekte gleich sind (laut `Equals()`), müssen sie zwingend denselben Hash-Wert haben. Andernfalls landen inhaltlich identische Objekte in verschiedenen Fächern - und das Dictionary findet sie nicht mehr.

csharp
public override int GetHashCode()
{
  return HashCode.Combine(Marke, Modell, Baujahr);
}

Die Methode `HashCode.Combine()` ist ab .NET Core 2.1 verfügbar und nimmt dir die Arbeit ab, einen eigenen Hash-Algorithmus zu schreiben. Für ältere .NET Framework-Versionen nutzt du stattdessen dieses etablierte Muster:

csharp
public override int GetHashCode()
{
  int hash = 17;
  hash = hash * 31 + (Marke?.GetHashCode() ?? 0);
  hash = hash * 31 + (Modell?.GetHashCode() ?? 0);
  hash = hash * 31 + Baujahr.GetHashCode();
  return hash;
}

Das Muster mit Startwert 17 und Multiplikator 31 ist ein bewährter Ansatz, den du in vielen Codebases finden wirst. Warum gerade diese Zahlen? Sie reduzieren Kollisionen und sind primzahlenbasiert. Microsoft Learn - Object.GetHashCode-Methode erklärt die genauen Vertragsregeln.

Vollständiges Praxisbeispiel: Alle drei Methoden zusammen

Hier ist eine komplette Klasse, die alle drei Methoden korrekt überschreibt. Dieses Muster wirst du im Beruf häufig sehen - egal ob bei Fachinformatikern, im Studium oder bei Junior-Entwicklern.

csharp
using System;

public class Artikel : IEquatable<Artikel>
{
  public int Id { get; set; }
  public string Bezeichnung { get; set; }
  public decimal Preis { get; set; }

  public override string ToString()
  {
    return $"[#{Id}] {Bezeichnung} - {Preis} EUR";
  }

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

  public bool Equals(Artikel anderes)
  {
    if (anderes == null) return false;
    return Id == anderes.Id &&
            Bezeichnung == anderes.Bezeichnung &&
            Preis == anderes.Preis;
  }

  public override int GetHashCode()
  {
    return HashCode.Combine(Id, Bezeichnung, Preis);
  }
}

// Test
Artikel a1 = new Artikel { Id = 1, Bezeichnung = "USB-Kabel", Preis = 9.99m };
Artikel a2 = new Artikel { Id = 1, Bezeichnung = "USB-Kabel", Preis = 9.99m };

Console.WriteLine(a1.ToString());    // Ausgabe: [#1] USB-Kabel - 9,99 EUR
Console.WriteLine(a1.Equals(a2));    // True
Console.WriteLine(a1.GetHashCode() == a2.GetHashCode());  // True

Das Interface `IEquatable<Artikel>` implementiert die typsichere Variante von `Equals()`. Warum? Weil du damit unnötige Boxing-Operationen vermeidest. Boxing bedeutet das Umwandeln von Werttypen in Referenztypen, was Performance kostet. Bei primitiven Typen wie `int` oder bei `struct` macht das einen spürbaren Unterschied.

Häufige Fehler, die Anfänger machen

Fehler 1: GetHashCode() nicht überschrieben

Wenn du `Equals()` überschreibst, aber `GetHashCode()` vergisst, bricht der Vertrag zwischen beiden Methoden. Das Resultat: Zwei als "gleich" erkannte Objekte haben unterschiedliche Hash-Werte. In einem `Dictionary` findest du sie dann nicht mehr - obwohl sie eigentlich gleich sind.

Fehler 2: Equals() mit falschem Typ-Vergleich

Ein klassischer Anfängerfehler ist es, den Typ in `Equals()` nicht zu prüfen. Dann knallt der Cast oder du vergleichst Äpfel mit Birnen.

csharp
// FALSCH: Keine Typpruefung, keine Nullpruefung
public override bool Equals(object obj)
{
  Auto anderes = (Auto)obj;  // Exception bei falschem Typ!
  return Marke == anderes.Marke;
}

// RICHTIG: Typ und Null pruefen
public override bool Equals(object obj)
{
  if (obj is Auto anderes)
  {
    return Marke == anderes.Marke;
  }
  return false;
}

Das Pattern `if (obj is Auto anderes)` nennt sich Pattern Matching und ist ab C# 7.0 verfügbar. Es ist kompakter und sicherer als der explizite Cast.

Fehler 3: Veränderliche Felder im Hash-Code verwenden

Wenn du ein Objekt in ein `HashSet` steckst und danach die Felder änderst, die in `GetHashCode()` einfließen, ändert sich der Hash-Wert. Das HashSet kann das Objekt dann nicht mehr finden. Nutze für Hash-Berechnungen idealerweise unveränderliche Felder wie eine ID.

Übungstipp: Baue dir eine eigene Klasse

Nimm eine Klasse aus deinem Alltag - `Schueler`, `Rechnung`, `Spielkarte`, was immer dir einfällt. Implementiere alle drei Methoden. Teste dann mit zwei identischen Objekten in einem `HashSet<T>`. Wenn dein Code korrekt ist, wird das zweite Objekt nicht hinzugefügt, weil es als "gleich" erkannt wird.

Das Üben mit konkreten Beispielen hilft dir, die Konzepte zu verinnerlichen - egal ob du für die IHK-Zwischenprüfung lernst oder dich auf ein Vorstellungsgespräch vorbereitest.

FAQ: Häufige Fragen zu C# ToString Equals GetHashCode

Muss ich alle drei Methoden überschreiben?

Nein. Du überschreibst nur die, die du brauchst. Wenn deine Objekte nie in Hash-Tabellen landen und du keine inhaltlichen Vergleiche brauchst, reicht die Standardimplementierung. In der Praxis überschreibt man `ToString()` fast immer, `Equals()` und `GetHashCode()` nur bei Bedarf.

Was passiert, wenn Equals true zurückgibt, die Hash-Codes aber unterschiedlich sind?

Dann ist dein Code kaputt. Der Vertrag lautet: Wenn zwei Objekte gleich sind, müssen ihre Hash-Codes identisch sein. Umgekehrt gilt das nicht - zwei Objekte mit gleichem Hash-Code können ungleich sein (das nennt man Hash-Kollision).

Kann ich Equals mit dem == Operator vergleichen?

Bei Referenztypen vergleicht `==` standardmäßig die Referenz, nicht den Inhalt. Überschreibst du `Equals()`, ändert das nichts am `==`-Operator. Wenn du auch `==` inhaltlich vergleichen willst, musst du den Operator zusätzlich überladen. Bei Werttypen (`struct`) vergleicht `==` bereits die Inhalte, sofern du ihn definiert hast.

Wann brauche ich IEquatable<T>?

`IEquatable<T>` ist die typsichere Variante von `Equals()`. Statt ein `object` zu übergeben und casten zu müssen, nimmst du direkt den richtigen Typ. Das vermeidet Boxing und ist performanter. Sinnvoll ist das bei Performance-kritischem Code oder bei Werttypen.

Gilt das alles auch für structs?

Ja, aber bei `struct` sind die Regeln etwas anders. `Equals()` vergleicht bei Structs standardmäßig alle Felder über Reflection (das Auslesen der Struktur zur Laufzeit) - was sehr langsam ist. Auch hier lohnt sich das Überschreiben. Zudem empfiehlt sich bei Structs immer die Implementierung von `IEquatable<T>`, um Boxing zu vermeiden.

Fazit

Die drei Methoden `ToString()`, `Equals()` und `GetHashCode()` gehören zu den absoluten Grundlagen, die jeder C#-Entwickler beherrschen muss. `ToString()` macht deine Objekte lesbar, `Equals()` erlaubt inhaltliche Vergleiche und `GetHashCode()` ist der Schlüssel zu performanten Collections. Werden sie richtig implementiert, funktioniert dein Code zuverlässig und ist deutlich leichter zu debuggen. Das Beherrschen von C# ToString Equals GetHashCode unterscheidet Anfänger von echten Profis.

Wenn du bei OOP-Konzepten wie Vererbung, Überschreiben vs. Überladen oder dem `base`-Keyword noch unsicher bist, lohnt sich gezielte Nachhilfe. Bei study-it.education findest du erfahrene Tutoren, die dir C#-Grundlagen und fortgeschrittene Themen praxisnah erklären - egal ob du Azubi, Student oder Berufseinsteiger bist.


Matching tutoring

Want 1:1 help with this topic?

First chat · €0 · 30 min

Need someone to walk through this with you?

Instead of re-reading: 30 min with a senior dev.

Book a free first chat →
About the author
Marcel Schmidtpeter
Marcel Schmidtpeter

Die Object-Klasse in C# liefert essenzielle Methoden. Verstehe ToString, Equals & GetHashCode – wichtig für Azubis, Studenten & Berufseinsteiger.

marcel.schmidtpeter@study-it.education →
Keep reading

More reading