1. Einführung
Stell dir vor, du bist Besitzer eines kleinen Ladens und hast eine Liste von Produkten. Jedes Produkt hat eine eigene, einzigartige Artikelnummer (zum Beispiel ART-001, ART-002) und natürlich einen Namen, Preis und Lagerbestand.
Wenn du das alles in einer List<T> speichern würdest, wobei T z.B. unsere zukünftige Klasse Product ist, dann müsstest du, um das Produkt mit der Artikelnummer ART-005 zu finden, die ganze Liste durchgehen:
"Ist das ART-001? Nein. Ist das ART-002? Nope... Und das hier ART-005! Gefunden!"
Bei 10 Produkten ist das kein Problem. Aber was, wenn du 10.000 Produkte hast? Oder 100.000? Das Suchen jedes Produkts würde ewig dauern. Dein Kunde müsste ewig warten, bis du sein Lieblingskeks gefunden hast. Nicht cool!
Wir brauchen einen Weg, wie wir sofort zum gewünschten Produkt springen können, wenn wir seine eindeutige Artikelnummer kennen, ohne alles andere durchzugehen. Also brauchen wir einen "Key", der direkt auf den gewünschten "Value" zeigt.
Kennenlernen von Dictionary
Und hier kommt Dictionary<TKey, TValue> ins Spiel! Stell dir vor, das ist nicht einfach eine Liste, sondern ein richtig schlaues Telefonbuch. Im normalen Telefonbuch suchst du die Telefonnummer (Value) nach dem Namen (Key) der Person. Du schlägst das Buch bei "A" auf, suchst "Alex", und da ist seine Nummer. Du musst nicht alle Nummern durchgehen, bis du die richtige findest.
Genauso speichert Dictionary (auf Deutsch "Wörterbuch") Daten als "Key-Value"-Paare.
- Key (TKey): Das ist der eindeutige Identifikator für jedes Element. Wie der Name im Telefonbuch oder die Artikelnummer. Mit diesem Key suchst du den Value. Der Key muss einzigartig im Dictionary sein. Versuchst du, einen Eintrag mit einem schon vorhandenen Key hinzuzufügen, lässt Dictionary das nicht zu.
- Value (TValue): Das sind die eigentlichen Daten, die du speichern willst. Das kann eine Telefonnummer sein, der Preis eines Produkts, eine Begriffserklärung – was auch immer!
Die Buchstaben TKey und TValue in den spitzen Klammern <TKey, TValue> bedeuten, dass Dictionary eine generische (Generic) Collection ist. Du entscheidest selbst, welchen Datentyp dein Key und welchen dein Value hat. Das kann string als Key sein (Name, Artikelnummer), int (User-ID) oder sogar deine eigene Klasse. Der Value kann int, string, double oder auch ein ganzes Objekt sein.
Vorteil? Sofortiger Zugriff! Dank einer speziellen internen Struktur (Hash-Tabelle, falls du’s genau wissen willst – aber keine Sorge, das musst du jetzt noch nicht verstehen), kann Dictionary einen Value per Key extrem schnell finden, egal ob das Dictionary zehn oder eine Million Einträge hat. Das ist wie ein Super-Index in einer riesigen Bibliothek: Du sagst "Ich brauche das Buch über C#", und sofort wird dir gezeigt, wo es liegt – ohne dass du jedes Regal durchblättern musst.
Genug Theorie, lass uns loslegen! Wir bauen unser Projekt weiter aus und erstellen ein interaktives "C#-Begriffs-Wörterbuch", das uns hilft, neue Begriffe zu merken.
2. Syntax-Basics: Wir erstellen ein Dictionary
Wie immer: Wir deklarieren eine Variable, aber diesmal geben wir nicht einen, sondern zwei Typen an – den Typ für den Key (TKey) und den Typ für den Value (TValue):
// Einfaches Dictionary: Key - string (Login), Value - string (E-Mail)
Dictionary<string, string> userEmails = new Dictionary<string, string>();
// Oder kürzer mit var
var userEmails = new Dictionary<string, string>();
Warum muss man beide Typen angeben?
Weil C# eine streng typisierte Sprache ist und das Dictionary wissen muss, welche Typen du für Keys und Values vorgesehen hast.
Elemente hinzufügen
Um ein neues "Key-Value"-Paar hinzuzufügen, benutzt du die Methode Add. Der Key muss einzigartig sein!
userEmails.Add("charlie", "charlie@example.com");
userEmails.Add("peter", "peter@gmail.com");
Wenn du nochmal mit dem gleichen Key hinzufügst – ist das Dictionary beleidigt und wirft eine Exception.
Zugriff auf Values per Key
Das Coolste am Dictionary: Du bekommst den Value direkt per Key:
string email = userEmails["charlie"];
Console.WriteLine(email); // charlie@example.com
Wenn du einen nicht existierenden Key abfragst, schreit das Programm sofort (es gibt eine KeyNotFoundException). Damit das nicht passiert, schauen wir uns gleich Methoden an, um zu prüfen, ob ein Key existiert.
Value per Key ändern
Wenn der Key schon existiert, einfach einen neuen Value zuweisen:
userEmails["charlie"] = "charlie@newmail.ru"; // jetzt ist Vasyas E-Mail geändert
Wenn der Key noch nicht da war – wird so ein neuer Eintrag im Dictionary erstellt.
Beispiel mit Usern
Lass uns unsere Lern-App etwas aufmotzen. Wir hatten eine Aufgabenliste (List<string> tasks;) für ein ToDo-Programm. Jetzt wollen wir "Login" einbauen: Jeder User braucht eine E-Mail.
So könnte das aussehen:
// UserId ist string, E-Mail auch string
var users = new Dictionary<string, string>();
users.Add("admin", "admin@myapp.com");
users.Add("alice", "alice@wonderland.com");
users.Add("bob", "bob@builder.com");
Jetzt kannst du immer blitzschnell die E-Mail eines Users per Login rausfinden:
Console.WriteLine(users["alice"]); // => alice@wonderland.com
3. Wichtige Methoden und Properties von Dictionary
| Methode/Property | Beschreibung |
|---|---|
|
Fügt ein neues "Key-Value"-Paar hinzu. |
|
Löscht ein Element per Key. |
|
Prüft, ob es diesen Key gibt. |
|
Prüft, ob es diesen Value gibt (langsam!). |
|
Holt sicher einen Value per Key, ohne Exception zu werfen. |
|
Anzahl der "Key-Value"-Paare im Dictionary. |
|
Collection aller Keys. |
|
Collection aller Values. |
Key-Existenz prüfen
Das Gängigste (und Sicherste) ist, erst zu checken, ob ein Key existiert:
if (users.ContainsKey("dorothy"))
{
Console.WriteLine(users["dorothy"]);
}
else
{
Console.WriteLine("User dorothy nicht gefunden!");
}
Sicherer Weg: TryGetValue
Die Methode TryGetValue verhindert Exceptions:
if (users.TryGetValue("bob", out string email))
{
Console.WriteLine($"E-Mail von Bob: {email}");
}
else
{
Console.WriteLine("Bob nicht gefunden!");
}
Das ist Best Practice und wird sogar gern in Vorstellungsgesprächen gefragt – also gleich merken! Außerdem ist diese Methode schneller als das Duo ContainsKey + Zugriff per Index.
4. Dictionary durchgehen: foreach-Schleife
Wenn du alle Paare durchgehen willst, nimm die foreach-Schleife. Jedes Dictionary-Element ist ein Objekt vom Typ KeyValuePair<TKey, TValue>:
foreach (var pair in users)
{
Console.WriteLine($"Login: {pair.Key}, E-Mail: {pair.Value}");
}
Oder, wenn du es noch stylischer willst:
foreach (var (login, email) in users)
{
Console.WriteLine($"{login}: {email}");
}
// Dieser Syntax ist dank Tuple-Deconstruction (C# 7+) möglich.
5. Löschen und Ändern von Values
Einen User per Login löschen ist easy:
users.Remove("alice");
Wenn der Key nicht existiert – gibt’s false zurück. Du kannst also ruhig versuchen zu löschen, ohne Angst vor Exceptions.
E-Mail eines Users ändern:
users["bob"] = "bob@constructor.com";
Wenn der Key noch nicht da war – wird ein neues Paar angelegt!
6. Nützliche Properties Keys und Values
Wenn du nur die Liste der Logins (Keys) oder nur die E-Mails (Values) brauchst, nimm die Collections Keys und Values:
foreach (string login in users.Keys)
{
Console.WriteLine("Login: " + login);
}
foreach (string email in users.Values)
{
Console.WriteLine("E-Mail: " + email);
}
7. Wichtige Dictionary-Details
Keys müssen einzigartig sein
Du kannst also nicht zwei gleiche Keys hinzufügen. Versuchst du es – gibt’s eine Exception. Diese Einzigartigkeit sorgt für Datensicherheit: Ein User kann nicht zwei E-Mails gleichzeitig haben (pro Eintrag).
Key darf nicht null sein (bei string)
Bei string-Keys führt der Versuch, einen null-Key hinzuzufügen, zu einem Fehler (ArgumentNullException). Wenn du plötzlich keinen Key hast, überleg mal – vielleicht ist das ein Hinweis auf ein Problem in deiner Logik.
Warum ist die Suche im Dictionary so schnell?
Dictionary ist "unter der Haube" als Hash-Tabelle gebaut. Das heißt, die Suche per Key ist kein Durchgehen aller Elemente, sondern ein blitzschnelles Berechnen einer "Hash-Funktion" und fast direkter Zugriff auf die Zelle, wo der Value liegt.
Was kann man als Key benutzen?
- Jeden Typ, für den Gleichheit und ein eindeutiger Code korrekt implementiert sind (Methoden Equals und GetHashCode()).
- Meistens ist das string, int, Guid oder deine eigenen Typen (dann aber aufpassen mit Equals/GetHashCode, sonst gibt’s lustige Bugs).
8. Wir bauen das Dictionary ins App ein
In unserer kleinen ToDo-App fügen wir ein User-Dictionary hinzu und bauen eine Funktion, die E-Mails per Login sucht und Fehler abfängt:
using System;
using System.Collections.Generic;
class Program
{
static void Main()
{
// User-Dictionary: Login => E-Mail
var users = new Dictionary<string, string>
{
{ "admin", "admin@myapp.com" },
{ "alice", "alice@wonderland.com" },
{ "bob", "bob@builder.com" }
};
Console.WriteLine("Gib den Login des Users ein, um die E-Mail zu suchen:");
string login = Console.ReadLine();
// Sichere Suche nach E-Mail
if (users.TryGetValue(login, out string email))
{
Console.WriteLine($"E-Mail von User {login}: {email}");
}
else
{
Console.WriteLine($"User {login} nicht gefunden.");
}
// Alle User durchgehen
Console.WriteLine("\nListe aller User:");
foreach (var pair in users)
{
Console.WriteLine($"{pair.Key} => {pair.Value}");
}
}
}
9. Typische Fehler und Fallen für Anfänger
Manchmal will man unbedingt sowas machen:
// In der Hoffnung, dass nichts passiert, wenn der Key fehlt
string value = users["nonexistent"]; // Zack! KeyNotFoundException!
Vergiss nicht: Immer erst prüfen, ob der Key existiert (ContainsKey oder TryGetValue), wenn du nicht sicher bist, dass er da ist.
Denk auch dran: Wenn du alle Values durchgehst, sind die nicht unbedingt einzigartig! Ein und dieselbe E-Mail kann bei zwei Logins stehen (wenn du die Einzigartigkeit der Values verlierst, nicht der Keys).
Oft werden auch Methoden verwechselt – zum Beispiel versucht man, per Value zu löschen:
users.Remove("bob@builder.com"); // Löscht nichts! Erwartet wird ein Key, kein Value.
GO TO FULL VERSION