1. Kollektion OrderedDictionary
.NET hatte schon immer eine fette Standardbibliothek, aber im Alltag als Entwickler gab's immer wieder Kompromisse: Man will ein Dictionary, das sich die Reihenfolge merkt, oder braucht ein Set mit unveränderlichen, einzigartigen Werten. Vor .NET 9 musste man auf externe Bibliotheken zurückgreifen oder sich selbst was basteln (manche haben sogar GitHub aufgemacht und OrderedDictionary einfach kopiert – pssst, wir verraten's niemandem).
Mit .NET 9 gibt's jetzt neue generische Kollektionen – endlich Schluss mit Workarounds! Lass uns die zwei praktischsten davon genauer anschauen: OrderedDictionary<TKey, TValue> und ReadOnlySet<T>.
1. Was ist OrderedDictionary?
OrderedDictionary ist ein Hybrid aus Dictionary und Liste. Er speichert "Key-Value"-Paare wie ein normales Dictionary<TKey, TValue>, garantiert aber, dass die Reihenfolge der Elemente der Reihenfolge entspricht, in der sie hinzugefügt wurden. Das ist besonders wichtig, wenn du Elemente in genau der Reihenfolge durchgehen willst, wie der User sie eingegeben hat, oder wenn die Reihenfolge für die Business-Logik zählt: z.B. beim Drucken von Reports, Serialisieren von Daten, Generieren von Konfigurationen.
AnalogieWenn ein normales Dictionary wie ein Schrank mit vielen Fächern ist, wo du Sachen schnell rein- und rauslegen kannst, ohne auf die Reihenfolge zu achten, dann ist OrderedDictionary wie ein ordentlicher Schrank mit Schubladen. Da liegt alles schön sortiert, und du weißt immer, was zuerst und was zuletzt reingekommen ist.
2. Hauptunterschied zu Dictionary
- Dictionary: Die Reihenfolge der Elemente ist nicht garantiert (auch wenn es manchmal so aussieht – glaub's nicht, das ist nur Zufall!).
- OrderedDictionary: Die Elemente bleiben genau in der Reihenfolge, wie sie hinzugefügt wurden.
3. Syntax und wichtigste Methoden
Hier ein einfaches Beispiel:
using System.Collections.Generic;
var od = new OrderedDictionary<string, int>();
od.Add("Ivan", 5);
od.Add("Svetlana", 8);
od.Add("Alex", 3);
// Durchlaufen in der Reihenfolge der Hinzufügung:
foreach (var pair in od)
{
Console.WriteLine($"{pair.Key}: {pair.Value}");
}
Ausgabe:
Ivan: 5
Svetlana: 8
Alex: 3
Wenn du das gleiche Beispiel mit einem normalen Dictionary machst, ist die Reihenfolge meistens anders. Mit OrderedDictionary ist sie immer so, wie du sie hinzugefügt hast.
OrderedDictionary implementiert die gleichen Interfaces wie ein normales Dictionary:
- IDictionary<TKey, TValue>
- IReadOnlyDictionary<TKey, TValue>
- IEnumerable<KeyValuePair<TKey, TValue>>
4. Zugriff per Index und per Key
Das Besondere: OrderedDictionary hat einen Indexer sowohl für den Key als auch für den numerischen Index!
// Nach Name (Key):
int svetlanaScore = od["Svetlana"]; // 8
// Nach Index:
var firstEntry = od.ElementAt(0); // KeyValuePair<string, int>("Ivan", 5)
5. Aktualisieren und Entfernen
Wenn du ein neues Element mit einem schon existierenden Key hinzufügst, gibt's eine Exception. Wenn du den Wert ersetzen willst – nimm den Indexer:
od["Ivan"] = 10; // Ändert den existierenden, Reihenfolge bleibt gleich
Löschen geht sowohl per Key als auch per Index:
od.Remove("Svetlana");
od.RemoveAt(0); // löscht "Ivan"
6. Visualisierung der Struktur
flowchart LR
A("0: Ivan - 5")
B("1: Svetlana - 8")
C("2: Alex - 3")
A --> B --> C
7. Stolperfallen und Fehler
Viele Entwickler versuchen, Dictionary<TKey, TValue> zu benutzen und hoffen auf eine feste Reihenfolge – das ist eine Falle! Selbst wenn es bei manchen Daten klappt, kann es beim nächsten Mal anders sein (vor allem bei .NET-Updates oder auf einer anderen Plattform).
Bei OrderedDictionary sind manche Operationen (z.B. Einfügen oder Löschen in der Mitte) minimal langsamer als beim normalen Dictionary, weil die Reihenfolge gespeichert wird – aber für die meisten Anwendungsfälle überwiegen die Vorteile.
Wenn du oft per Index suchst – dann ist OrderedDictionary genau richtig. Wenn du nur schnellen Zugriff per Key brauchst und die Reihenfolge egal ist – nimm das normale Dictionary.
8. Praxisbeispiel für eine App
Angenommen, in unserer Mitarbeiter- und Abteilungs-App brauchen wir jetzt einen Report, in dem die Mitarbeiter in der Reihenfolge ausgegeben werden, wie sie hinzugefügt wurden:
var employeeScores = new OrderedDictionary<string, int>();
employeeScores.Add("Pjotr", 100);
employeeScores.Add("Anna", 150);
employeeScores.Add("Viktoria", 80);
// Jetzt ist der Report immer in der richtigen Reihenfolge:
foreach (var pair in employeeScores)
{
Console.WriteLine($"{pair.Key}: {pair.Value} Punkte");
}
2. Kollektion ReadOnlySet<T>
1. Was ist ReadOnlySet?
ReadOnlySet<T> ist eine unveränderliche (immutable) Menge von einzigartigen Werten. Früher musste man, um ein "read-only set" zu bauen, eine Kopie mit .ToHashSet() zurückgeben oder einen eigenen Wrapper schreiben. Jetzt gibt's eine Kollektion, in die man nach der Erstellung nichts mehr hinzufügen oder löschen kann. Das macht den Code sicherer und verhindert versehentliche Fehler durch Änderungen von außen.
AnalogieDas ist wie ein Notizbuch, in das du einzigartige Namen schreibst und... dann die Seiten laminierst. Niemand kann mehr was reinschreiben, rausreißen oder ändern.
2. Erstellen eines ReadOnlySet
Am einfachsten erstellst du eine unveränderliche Menge mit einer Extension-Methode:
var colors = new[] { "Rot", "Grün", "Blau", "Grün" };
var readOnlyColors = colors.ToReadOnlySet();
// Jetzt sind hier nur einzigartige Werte drin und man kann nichts mehr ändern:
foreach (var color in readOnlyColors)
Console.WriteLine(color);
Ausgabe:
Rot
Grün
Blau
Du kannst auch den direkten Konstruktor nehmen (wenn du willst):
var set = new ReadOnlySet<int>(new[] {1, 2, 2, 3, 5, 1}); // Es bleibt trotzdem 1,2,3,5
ReadOnlySet in den Microsoft Docs
3. Wichtige Eigenschaften und Methoden
- Nur Lesen (immutable)
- Count – Anzahl der Elemente
- Contains(item) – Prüft, ob ein Element drin ist
- Unterstützt LINQ-Queries (IEnumerable<T>)
- Schnelle Suche, aber kein Hinzufügen, Löschen oder Clear
Beispiel:
if (readOnlyColors.Contains("Rot"))
Console.WriteLine("Rot ist in der Liste!");
Das hier geht nicht:
// Compiler-Fehler!
readOnlyColors.Add("Gelb");
4. Wo ist das nützlich?
Sehr oft willst du nach außen eine Menge zurückgeben, aber niemand soll sie aus Versehen (oder absichtlich) ändern können. Zum Beispiel:
- Liste der unterstützten User-Rollen zurückgeben
- Liste erlaubter Dateiendungen
- Liste von einzigartigen Konfigurationsparametern, die nicht geändert werden dürfen
Beispiel in unserer App: Angenommen, es gibt eine Liste erlaubter Abteilungen:
public static ReadOnlySet<string> Departments { get; } =
new[] { "Personal", "Entwicklung", "Buchhaltung" }.ToReadOnlySet();
Jetzt kann niemand die Abteilungsliste von außen manipulieren.
5. Visualisierung: Unterschied zu normalem HashSet
graph LR
A[HashSet] -- Add/Remove/Contains --> B((Elemente))
C[ReadOnlySet] -- Only Contains --> D((Elemente))
3. OrderedDictionary vs. ReadOnlySet: Vergleichstabelle
| Kollektion | Speichert Paare? | Garantiert Reihenfolge | Veränderbar | Suche per Key | Suche per Index | Szenarien |
|---|---|---|---|---|---|---|
| OrderedDictionary | Ja, "Key-Value" | Ja | Ja | Ja | Ja | Karten, Einstellungen, Reports |
| ReadOnlySet | Nein, nur Werte | Nein | Nein | Ja | Nein | Sichere Mengen, Konstanten |
| HashSet | Nein, nur Werte | Nein | Ja | Ja | Nein | Mengen, die man ändern will |
| Dictionary | Ja, "Key-Value" | Nein | Ja | Ja | Nein | Karten ohne Reihenfolge-Anforderung |
GO TO FULL VERSION