C# IComparable IComparer einfach erklärt: So sortierst du Objekte
IComparable und IComparer bestimmen, wie Objekte in C# sortiert werden – einfach erklärt für Azubis, Studenten und Berufseinsteiger.
Von Marcel Schmidtpeter 21. Sept. 2026
Dein Programm läuft, die Liste mit 50 Kundenobjekten ist gefüllt - und dann wirft `List.Sort()` eine `InvalidOperationException` mit der Meldung „Failed to compare two elements in the array". Genau in diesem Moment stolperst du über das Thema dieses Artikels: C# kann Zahlen und Strings automatisch sortieren, aber bei deinen eigenen Objekten muss es erst lernen, *wonach* es sortieren soll. Die Schnittstellen IComparable und IComparer sind genau dafür da - egal, ob du gerade deine Ausbildung zum Fachinformatiker machst, im Studium sitzt oder im ersten Job auf legacy Code losgehst.
Was ist IComparable in C#?
IComparable ist eine Schnittstelle, mit der eine Klasse selbst festlegt, wie ihre Objekte verglichen werden - die sogenannte natürliche Sortierreihenfolge. Implementierst du `IComparable<T>`, sagst du C#: „So vergleiche ich mich mit einem anderen Objekt meines Typs."
Stell dir eine Schulklasse vor, die sich für ein Klassenfoto aufstellen soll. Bei `IComparable` wissen die Schüler selbst, wohin sie gehören - zum Beispiel alphabetisch nach Nachname. Niemand muss es ihnen sagen.
Die Schnittstelle besteht aus genau einer Methode: `CompareTo`. Sie gibt einen `int` zurück:
negativ, wenn das aktuelle Objekt *vor* dem anderen kommt
0, wenn beide gleich sind
positiv, wenn das aktuelle Objekt *nach* dem anderen kommt
Merke: `CompareTo` gibt nicht „größer" oder „kleiner" als `bool` zurück, sondern einen `int`: negativ = vorher, 0 = gleich, positiv = nachher. Diese drei Zustände brauchst du für stabile Vergleiche.
Die offizielle Dokumentation findest du bei Microsoft Learn.
IComparable an einem Beispiel
Hier eine Klasse `Artikel`, die sich nach Preis sortiert:
public class Artikel : IComparable<Artikel>
{
public string Name { get; set; }
public decimal Preis { get; set; }
public int CompareTo(Artikel? other)
{
if (other == null)
{
return 1; // null gilt als "kleiner" -> aktuelles Objekt kommt danach
}
return this.Preis.CompareTo(other.Preis);
}
}Der Trick: `decimal` und `string` implementieren `CompareTo` bereits selbst. Du kannst also delegieren, statt die Logik selbst zu schreiben. Das ist weniger fehleranfällig als ein handgeschriebenes `this.Preis - other.Preis` - das klingt clever, kann aber bei Rundungsproblemen danebengehen.
Jetzt funktioniert `Sort()` ohne Argumente:
List<Artikel> lager = new List<Artikel>
{
new Artikel { Name = "Monitor", Preis = 199.99m },
new Artikel { Name = "Maus", Preis = 24.50m },
new Artikel { Name = "Tastatur", Preis = 79.90m }
};
lager.Sort(); // sortiert automatisch nach PreisWas ist IComparer in C#?
IComparer ist eine Schnittstelle für eine *separate* Vergleichsklasse - damit kannst du mehrere Sortierkriterien für denselben Typ definieren. Zurück zur Klassenfoto-Analogie: `IComparer` ist der Lehrer, der sagt „heute sortiert ihr nach Größe" und morgen „heute nach Alter". Die Schüler selbst (also deine Objekte) bleiben unverändert.
Das löst ein echtes Problem:
Merke: `IComparable` erlaubt genau eine natürliche Reihenfolge pro Typ. Brauchst du mehrere Sortierkriterien - z. B. Artikel mal nach Preis, mal nach Name -, kommst du um `IComparer<T>` nicht herum.
Die Implementierung sieht so aus:
public class ArtikelNameComparer : IComparer<Artikel>
{
public int Compare(Artikel? x, Artikel? y)
{
if (x == null && y == null)
{
return 0;
}
if (x == null)
{
return -1;
}
if (y == null)
{
return 1;
}
return string.Compare(x.Name, y.Name, StringComparison.Ordinal);
}
}Die Verwendung sieht so aus:
var nameComparer = new ArtikelNameComparer();
lager.Sort(nameComparer); // sortiert jetzt nach NameDoku dazu: IComparer<T> auf Microsoft Learn.
IComparable oder IComparer - wann nutzt du was?
Die einfache Regel: `IComparable` gehört in die Klasse, wenn es ein offensichtliches, übergeordnetes Sortierkriterium gibt. `IComparer` (oder ein Lambda) nutzt du für alles andere.
Kriterium | IComparable<T> | IComparer<T> |
Wo implementiert? | In der Klasse selbst | In einer separaten Klasse |
Anzahl Kriterien | Genau eins pro Typ | Beliebig viele |
Aufruf | `liste.Sort()` | `liste.Sort(comparer)` |
Typischer Einsatz | „Natürliche" Reihenfolge (z. B. `Person` nach `Id`) | Wechselnde Sortierungen (Name, Preis, Datum) |
Klasse ändern nötig? | Ja | Nein - funktioniert auch mit Fremdcode |
Für schnelle Einmal-Sortierungen brauchst du übrigens keine eigene Comparer-Klasse. `Sort()` akzeptiert auch ein Lambda vom Typ `Comparison<T>` - wie das genau funktioniert, habe ich im Artikel zu C# Lambda Expressions erklärt:
lager.Sort((a, b) => string.Compare(a.Name, b.Name, StringComparison.Ordinal));Noch ein Hinweis für Studenten und Prüfungskandidaten: Bei LINQ nutzt du stattdessen `OrderBy` - das braucht kein `IComparable` auf der Klasse, weil du das Kriterium direkt mitgibst. Mehr dazu im Beitrag zu LINQ filtern und transformieren. Wenn du auch Python lernst: Dort löst du dieselbe Aufgabe mit `__lt__`, siehe Python Objekte sortieren mit sorted().
3 häufige Fehler bei IComparable und IComparer
Fehler 1: Sortieren ohne Implementierung. Rufst du `Sort()` auf einer `List<T>` auf, deren Typ weder `IComparable` implementiert noch ein Vergleichskriterium mitbekommt, fliegt dir eine `InvalidOperationException` um die Ohren. C# kann nicht raten, ob `artikel1 < artikel2` nach Preis oder Name gemeint ist.
Fehler 2: Rückgabewert falsch herum. Wer `other.Preis.CompareTo(this.Preis)` schreibt, sortiert absteigend statt aufsteigend - der Code kompiliert trotzdem fehlerfrei. Merke: `this` links, `other` rechts ergibt aufsteigend. Willst du absteigend sortieren, tauschst du gezielt die Operanden oder drehst das Ergebnis mit `-` um.
Fehler 3: Null-Checks vergessen. Fehlt die `null`-Prüfung in `CompareTo`, knallt es spätestens, wenn die Liste ein `null`-Element enthält - mit einer `NullReferenceException` mitten im Sortiervorgang. Besonders tückisch: Der Fehler tritt nicht beim `Sort()`-Aufruf selbst auf, sondern tief im Framework. Wie du `null` generell sauber behandelst, steht im Artikel zu Nullable-Typen in C#.
Übungstipp: Baue deine eigene Sortierlogik
Nimm dir 20 Minuten und erstelle eine Klasse `Song` mit den Properties `Titel`, `Interpret` und `Dauer` (als `int` in Sekunden). Implementiere `IComparable<Song>` so, dass nach Dauer sortiert wird. Schreibe danach einen `SongTitelComparer`, der nach Titel sortiert. Teste beide mit `Sort()` und gib die Liste mit einer `foreach`-Schleife aus.
Warum das funktioniert? Weil du dabei beide Schnittstellen einmal komplett selbst geschrieben hast - genau das wird in Prüfungen (z. B. IHK-Abschlussprüfung Teil 1) und in Vorstellungsgesprächen abgefragt. Grundlagen zu Listen findest du im Überblick zu C# Collections, die Typ-Grundlagen zu `<T>` im Beitrag zu Generics.
FAQ: Häufige Fragen zu IComparable und IComparer
Was gibt CompareTo zurück?
Einen `int`: einen negativen Wert, wenn das aktuelle Objekt vor dem Vergleichsobjekt einsortiert wird, `0` bei Gleichheit und einen positiven Wert, wenn es danach kommt. Viele nutzen dafür einfach `-1`, `0` und `1`.
Funktioniert List.Sort() ohne IComparable?
Nein. Wenn der Typ `IComparable` nicht implementiert und kein Comparer übergeben wird, wirft `Sort()` eine `InvalidOperationException`. Zahlen, Strings und `DateTime` implementieren die Schnittstelle übrigens von Haus aus - bei eigenen Klassen musst du selbst liefern.
Wann IComparable und wann IComparer?
`IComparable` für die eine, natürliche Standard-Sortierung, die in die Klasse gehört. `IComparer` für zusätzliche oder wechselnde Sortierkriterien - besonders bei Klassen, die du nicht ändern kannst oder darfst.
Kann ich auch ohne eigene Comparer-Klasse sortieren?
Ja, mit einem Lambda: `liste.Sort((a, b) => ...)`. Für größere Projekte ist eine benannte Comparer-Klasse aber wartbarer und wiederverwendbar. Alternativ bietet sich LINQ mit `OrderBy` an.
Gibt es einen Unterschied zwischen IComparable und IComparable<T>?
Ja. Die generische Version `IComparable<T>` ist typsicher und sollte heute Standard sein. Das nicht-generische `IComparable` stammt aus der Zeit vor Generics und arbeitet mit `object`, erfordert also Casting.
Fazit
`IComparable` und `IComparer` ergänzen sich: Ersteres gibt deiner Klasse eine natürliche Sortierreihenfolge, letzteres liefert flexible Zusatzsortierungen von außen. Wenn du einmal verinnerlicht hast, dass `CompareTo` nur „negativ, null, positiv" zurückgibt, kannst du jede Objektliste in C# sortieren - vom Lagerbestand bis zur Kundenliste.
Wenn du bei C#, OOP oder der Prüfungsvorbereitung gerade festhängst: Bei study-it.education bekommst du persönliche IT-Nachhilfe - ob Azubi, Student oder Quereinsteiger. Schau vorbei, wir sortieren deine Wissenslücken schneller als jeder Comparer.
1:1-Hilfe zu diesem Thema?
Brauchst du jemand, der das mit dir durchgeht?
Statt nochmal lesen: 30 min mit einem Senior-Dev.
Kostenloses Erstgespräch buchen →
IComparable und IComparer bestimmen, wie Objekte in C# sortiert werden – einfach erklärt für Azubis, Studenten und Berufseinsteiger.
marcel.schmidtpeter@study-it.education →Mehr Lesestoff
C# JSON mit System.Text.Json lesen & schreiben – einfach erklärt
JSON-Daten in C# lesen und schreiben? Mit System.Text.Json gelingt dir Serialisierung & Deserialisierung – einfach erklärt für alle IT-Einsteiger.
C# xUnit Unit Test: So schreibst du deine ersten Unit Tests
Unit Tests mit xUnit machen deinen C#-Code belastbar. In diesem Tutorial lernst du [Fact], [Theory] und Assert kennen – für Einsteiger erklärt.
C# Datenbank verbinden: ADO.NET & Entity Framework einfach erklärt
So greifst du aus C# auf Datenbanken zu: mit ADO.NET für direktes SQL oder EF Core als modernem ORM – beide Wege mit Beispielen erklärt.