1. Einführung
Wenn du schon mal eine Schublade voller Socken hattest und ein Paar gesucht hast, kennst du das Sortierproblem. Wenn alles durcheinander liegt, wird das Finden zur Quest. Mit Kollektionen im Programmieren ist es genau das Gleiche.
Sortieren bedeutet, die Elemente einer Kollektion nach einem bestimmten Kriterium zu ordnen (zum Beispiel alphabetisch, nach Wert, Datum usw.). Das ist wichtig für:
- Anzeige von Daten für den User (niemand mag Chaos).
- Einfacheres Suchen (z.B. Binary Search geht nur bei sortierten Kollektionen).
- Vergleiche, Reports, Export und andere Aktionen.
Die Millionenfrage: "Und wenn ich nur fünf Elemente habe, muss ich dann sortieren?" – Theoretisch nein, aber sobald aus fünf fünfhundert oder fünftausend werden, kommst du um Automatisierung nicht herum.
In .NET gibt es zwei Hauptansätze zum Sortieren:
- Die Original-Kollektion verändern (z.B. List<T> mit der Sort-Methode sortieren).
- Eine neue, sortierte Kopie der Kollektion erstellen (z.B. Array klonen und dann sortieren).
Listen sortieren mit der Methode .Sort()
Die Methode Sort() gibt's bei der Klasse List<T>, weil diese das Interface IList<T> implementiert und damit Zugriff per Index und das Ändern der Reihenfolge erlaubt.
Beispiel – Zahlen aufsteigend sortieren:
using System;
using System.Collections.Generic;
class Program
{
static void Main()
{
var numbers = new List<int> { 5, 2, 9, 1, 5, 6 };
numbers.Sort();
Console.WriteLine("Sortierung aufsteigend:");
foreach(var number in numbers)
{
Console.Write($"{number} "); // 1 2 5 5 6 9
}
}
}
Hier wird "in place" sortiert: Die Original-Liste numbers wird verändert, die Elemente werden umsortiert.
Strings sortieren
Sortieren klappt auch super mit Strings:
var words = new List<string> { "apelsin", "yabloko", "banan", "grusha" };
words.Sort();
Console.WriteLine(string.Join(", ", words)); // apelsin, banan, grusha, yabloko
Fun Fact: Standardmäßig wird nach Unicode sortiert, nicht nach "menschlichem" Alphabet (vor allem bei verschiedenen Sprachen, also aufpassen bei mehrsprachigen Apps).
2. Sortieren nach eigenen Regeln
Manchmal reicht die "Standard"-Sortierung nicht. Zum Beispiel willst du User nicht nach Name, sondern nach Alter oder Registrierungsdatum sortieren.
Sortieren mit Lambda-Ausdruck (Methode Sort(Comparison<T>))
Die Sort-Methode kann man so aufrufen, dass man eine eigene Vergleichsfunktion übergibt.
User nach Alter sortieren:
class User
{
public string Name { get; set; }
public int Age { get; set; }
}
// ...
var users = new List<User>
{
new User { Name = "Alisa", Age = 30 },
new User { Name = "Bob", Age = 25 },
new User { Name = "Eva", Age = 35 }
};
users.Sort((u1, u2) => u1.Age.CompareTo(u2.Age));
foreach (var user in users)
{
Console.WriteLine($"{user.Name}: {user.Age}");
}
// Ausgabe:
// Bob: 25
// Alisa: 30
// Eva: 35
Wie funktioniert das? Das Lambda (u1, u2) => u1.Age.CompareTo(u2.Age) gibt eine negative Zahl zurück, wenn u1 jünger ist, eine positive wenn älter, und 0, wenn das Alter gleich ist.
Das Interface IComparer<T> verwenden
Manchmal will man die Sortierregel in eine eigene Klasse auslagern, z.B. wenn man viele Kollektionen und komplexe Logik hat.
class UserAgeComparer : IComparer<User>
{
public int Compare(User x, User y)
{
return x.Age.CompareTo(y.Age);
}
}
// ...
var users = new List<User>{ /* ... */ };
users.Sort(new UserAgeComparer()); // jetzt nach Alter sortiert
Das ist praktisch, wenn man die Sortierung an mehreren Stellen braucht oder viele Sortierarten hat.
Sortieren nach mehreren Feldern von Hand
Wenn einige User das gleiche Alter haben, du aber innerhalb der Altersgruppe nach Name sortieren willst:
users.Sort((u1, u2) => {
int ageCompare = u1.Age.CompareTo(u2.Age);
if (ageCompare != 0)
return ageCompare;
else
return u1.Name.CompareTo(u2.Name);
});
Jetzt wird erst nach Alter, dann nach Name sortiert.
3. Sortieren einer Kopie der Kollektion (ohne das Original zu ändern)
Wenn du die Original-Liste nicht verändern willst, kopiere sie vor dem Sortieren:
var copy = new List<int>(numbers);
copy.Sort();
Für eigene Objekte genauso:
var usersCopy = new List<User>(users);
usersCopy.Sort((a, b) => a.Age.CompareTo(b.Age));
4. Arrays sortieren
Mit Arrays (T[]) ist es auch easy:
int[] numbers = { 4, 2, 9, 7 };
Array.Sort(numbers); // das Original-Array wird verändert
Für "eigene" Sortierung:
Array.Sort(numbers, (a, b) => b.CompareTo(a)); // absteigend sortieren
Achtung: Array.Sort verändert das Original-Array und gibt kein neues zurück. Wenn du das Original behalten willst, kopiere das Array vorher:
int[] oldNumbers = { 3, 2, 1 };
int[] copy = (int[])oldNumbers.Clone();
Array.Sort(copy);
5. "Sortieren" von Dictionaries (Dictionary<TKey, TValue>)
Dictionary<TKey, TValue> ist von Natur aus ungeordnet (d.h. die Reihenfolge beim Durchlaufen ist nicht garantiert). Aber manchmal will man "sortierte Paare" bekommen.
Um sortierte Keys oder Values zu bekommen, erstelle eine Liste, kopiere die Paare rein und sortiere wie du willst:
var dict = new Dictionary<string, int>
{
{ "yabloko", 2 },
{ "apelsin", 5 },
{ "grusha", 3 }
};
// Nach Key sortieren:
var keyValueList = new List<KeyValuePair<string, int>>(dict);
keyValueList.Sort((a, b) => a.Key.CompareTo(b.Key));
foreach (var kv in keyValueList)
{
Console.WriteLine($"{kv.Key}: {kv.Value}");
}
// Nach Value sortieren:
keyValueList.Sort((a, b) => a.Value.CompareTo(b.Value));
foreach (var kv in keyValueList)
{
Console.WriteLine($"{kv.Key}: {kv.Value}");
}
Wenn du eine sortierte Liste von Keys oder Values brauchst:
var sortedKeys = new List<string>(dict.Keys);
sortedKeys.Sort();
var sortedValues = new List<int>(dict.Values);
sortedValues.Sort();
Aber denk dran: Die Dictionary-Struktur bleibt unverändert – du bekommst nur eine sortierte Aufzählung. In .NET 9 kommt OrderedDictionary<TKey, TValue>, der die Reihenfolge der Elemente speichert. Braucht man nicht oft, aber manchmal ist es praktisch.
6. Nützliche Besonderheiten
Muss man das Vergleichs-Interface implementieren?
Ganz einfach: Wenn deine Objekte "wissen" sollen, wie sie sich vergleichen (z.B. nach Datum oder Name), implementiere das Interface IComparable<T>.
class Product : IComparable<Product>
{
public string Name { get; set; }
public decimal Price { get; set; }
public int CompareTo(Product other)
{
return Price.CompareTo(other.Price);
}
}
Jetzt kannst du:
var products = new List<Product> { /* ... */ };
products.Sort(); // sortiert nach Preis
Wenn dir der Standardvergleich nicht passt – nutze IComparer<T> oder gib ein Lambda an, wie oben gezeigt.
User-Liste alphabetisch sortieren
Angenommen, wir haben in der App eine User-Liste:
List<string> users = new List<string> { "Viktor", "Anna", "Ekaterina", "Boris" };
users.Sort(); // jetzt ist users sortiert: Anna, Boris, Ekaterina, Viktor
Aufgaben nach Dringlichkeit sortieren
class Task
{
public string Title { get; set; }
public int Priority { get; set; } // 1 - dringend, 2 - wichtig, 3 - kann warten
}
var todo = new List<Task>
{
new Task { Title = "Hausaufgaben machen", Priority = 2 },
new Task { Title = "Brot kaufen", Priority = 1 },
new Task { Title = "Serie schauen", Priority = 3 }
};
todo.Sort((a, b) => a.Priority.CompareTo(b.Priority));
foreach (var task in todo)
Console.WriteLine($"{task.Priority}: {task.Title}");
Vergleich der Sortiermethoden
| Kollektion | Wird in place verändert? | Methode zum Sortieren | Kann man eine Regel angeben? |
|---|---|---|---|
|
Ja | |
Ja: Lambda oder IComparer |
|
Ja | |
Ja: Lambda oder IComparer |
|
Nein | – (Liste erstellen und sortieren) | Ja: über Lambda oder IComparer |
7. Typische Fehler und Besonderheiten beim Sortieren
Sortieren in place – verändert die Original-Kollektion! Wenn die Originaldaten nicht verändert werden sollen – kopiere sie vorher.
Versuch, eine unveränderbare Kollektion zu sortieren (z.B. ReadOnlyCollection<T>) führt zu einem Laufzeitfehler.
String-Vergleich ist je nach Kultur unterschiedlich: Das Sortieren von Strings (vor allem mit Kyrillisch, Umlauten usw.) kann je nach Locale anders sein. Für korrekte Sortierung nutze Comparer.Create(...) mit der gewünschten Kultur.
Sortieren von Dictionaries verändert deren Struktur nicht – du bekommst immer eine neue Sequenz von Paaren (oder eine neue Liste).
Für komplexe Sortierung nutze das Interface IComparer<T> mit deiner Logik.
Hier ein Beispiel für falsches Sortieren (klassische Stolperfalle):
var numbers = new List<int> { 1, 2, 3 };
var sorted = numbers.Sort(); // FEHLER: Sort() gibt void zurück!
Richtig:
numbers.Sort(); // verändert numbers in place
// Wenn du eine neue Kollektion willst:
var sorted = new List<int>(numbers);
sorted.Sort();
GO TO FULL VERSION