1. Introduction
Imagine : tu viens de décrocher un taf dans un labo secret qui étudie les chats. On te file une mission — créer un dico électronique des chats, où tu peux retrouver vite fait l’âge, la couleur et la taille de la queue d’un chat par son nom. La solution toute faite existe déjà — c’est Dictionary<string, Cat>. Mais voilà le hic : plus tard, le boss débarque et dit que pour certaines races rares, il faut que le dico garde l’ordre d’ajout, et parfois il doit aussi se supprimer selon une logique spéciale.
Et si tu dois écrire une méthode qui prend n’importe quel «dico de chats» ? Peu importe la classe exacte — ce qui compte, c’est qu’elle gère les opérations de base «clé-valeur». C’est là que l’interface IDictionary<TKey, TValue> entre en scène.
IDictionary<TKey, TValue> — c’est un contrat général qui définit ce qu’est un dico dans .NET. Ce n’est pas une classe concrète, mais une interface, c’est-à-dire un ensemble de règles que doit respecter tout vrai dictionnaire :
- Recherche rapide par clé
- Ajout et suppression de paires «clé-valeur»
- Parcourir toutes les paires
- Vérifier si une clé existe
Si Java avait existé au Moyen Âge, ses chevaliers auraient combattu les dragons non pas avec des épées, mais avec des clés et des valeurs. Et les devs C# auraient juste implémenté IDictionary<TKey, TValue> — et le dragon (ton code) serait vaincu.
2. Tableau de l’interface IDictionary
Regardons les principales «promesses» (membres) de cette interface :
| Membre de l’interface | Type | Description |
|---|---|---|
|
Propriété | Indexeur. Permet d’obtenir ou de définir la valeur associée à une clé donnée. En lecture : si la clé n’existe pas, ça balance une KeyNotFoundException. En écriture : si la clé n’existe pas, ça ajoute une nouvelle paire ; si la clé existe, ça met à jour la valeur. Important : c’est la façon la plus courante de bosser avec les dicos. |
|
Propriété | Renvoie une collection contenant toutes les clés du dico. Permet de parcourir juste les clés. |
|
Propriété | Renvoie une collection contenant toutes les valeurs du dico. Permet de parcourir juste les valeurs. |
|
Méthode | Ajoute la clé et la valeur données au dico. Si la clé existe déjà, ça balance une ArgumentException. |
|
Méthode | Détermine si le dico contient un élément avec la clé donnée. Renvoie true si la clé existe ; sinon — false. Super utile pour éviter les erreurs quand tu veux accéder à une clé qui n’existe pas via l’indexeur. |
|
Méthode | Supprime l’élément avec la clé donnée du dico. Renvoie true si l’élément a été trouvé et supprimé ; sinon — false (genre si la clé n’existait pas). |
|
Méthode | Récupère la valeur associée à la clé donnée. C’est la façon sécure d’obtenir une valeur si t’es pas sûr que la clé existe. Renvoie true si la clé existe, et value contient la valeur ; sinon — false, et value aura la valeur par défaut pour TValue. Cette méthode ne lance pas d’exception, ce qui la rend super populaire dans le code réel. |
3. Membres principaux de l’interface IDictionary<TKey, TValue>
Et maintenant — le plus important ! On va voir ce qu’il y a dans l’interface IDictionary<TKey, TValue>, et apprendre à utiliser ce «contrat» dans ton code.
public interface IDictionary<TKey, TValue> : ICollection<KeyValuePair<TKey, TValue>>, IEnumerable<KeyValuePair<TKey, TValue>>
{
TValue this[TKey key] { get; set; } // Indexeur pour accéder par clé
ICollection<TKey> Keys { get; }
ICollection<TValue> Values { get; }
void Add(TKey key, TValue value); // Ajouter une nouvelle paire (clé ne doit pas exister)
bool ContainsKey(TKey key); // Cette clé existe ?
bool Remove(TKey key); // Supprimer par clé
bool TryGetValue(TKey key, out TValue value); // Récupérer la valeur en mode safe
}
On décortique les points clés :
Indexeur [key]
Permet d’obtenir et de définir des valeurs par clé :
dictionary["Barsik"] = new Cat("Barsik", 2);
Propriétés Keys et Values
Permettent d’obtenir la collection de toutes les clés ou toutes les valeurs du dico.
foreach (var name in dictionary.Keys)
{
Console.WriteLine(name);
}
Méthodes Add, Remove, ContainsKey, TryGetValue
- Add(key, value) — ajouter une nouvelle paire
- Remove(key) — supprimer par clé
- ContainsKey(key) — vérifier si la clé existe
- TryGetValue(key, out value) — récupérer la valeur en mode safe (pas d’exception si la clé n’existe pas)
4. Utilisation de IDictionary<TKey, TValue> en pratique
Méthodes universelles
Imaginons que tu écris une fonction qui doit bosser avec un dico, mais tu veux pas savoir quelle classe c’est : un Dictionary classique, un SortedDictionary, ou même un «dico crypto-collectif» fait maison.
Tu déclares le paramètre en IDictionary<TKey, TValue> :
static void PrintDictionary<TKey, TValue>(IDictionary<TKey, TValue> someDictionary)
{
foreach (var pair in someDictionary)
{
Console.WriteLine($"{pair.Key}: {pair.Value}");
}
}
Maintenant ta méthode prend n’importe quel dico ! Sous le capot, ça peut être ce que tu veux — même un dico qui chiffre les valeurs, si t’es d’humeur funky.
Utiliser IDictionary pour passer des paramètres
Imaginons que tu fais une appli pour gérer les chats, et tu veux que ta méthode marche avec tous les dicos de paramètres possibles, pas juste une classe précise. Voilà à quoi ça ressemble :
void SetCatParameters(IDictionary<string, string> parameters)
{
if (parameters.ContainsKey("color"))
{
Console.WriteLine($"Peignez le chat en couleur : {parameters["color"]}");
}
}
Une signature unique — plusieurs implémentations
Petit tableau pour illustrer :
| Classe de collection | Implémente IDictionary<TKey,TValue> | Particularités |
|---|---|---|
|
✅ Oui | Recherche rapide, clés dans un ordre arbitraire |
|
✅ Oui | Clés automatiquement triées |
|
✅ Oui | Clés triées, plus économe en mémoire |
| (Classe maison qui implémente l’interface) | ✅ Oui | Ta logique à toi, mais tu dois respecter le contrat |
5. Lien avec d’autres interfaces de collections
Pour les vrais geeks : l’interface IDictionary<TKey, TValue> hérite de ICollection<KeyValuePair<TKey, TValue>> et IEnumerable<KeyValuePair<TKey, TValue>>. Ça veut dire que n’importe quel dico peut :
- Être parcouru avec foreach sur les paires clé-valeur,
- Ajouter et supprimer des paires via les méthodes de collection,
- Obtenir le nombre d’éléments.
foreach (var entry in myDictionary)
{
Console.WriteLine($"{entry.Key} => {entry.Value}");
}
6. Particularités et erreurs classiques
Bosser avec l’indexeur
L’erreur la plus fréquente des débutants : essayer d’obtenir un élément avec une clé absente va lancer une KeyNotFoundException.
var value = myDictionary["NoSuchKey"]; // Boom!
Donc il vaut mieux utiliser TryGetValue :
if (myDictionary.TryGetValue("Murzik", out var cat))
{
Console.WriteLine($"Chat trouvé : {cat}");
}
else
{
Console.WriteLine($"Chat non trouvé !");
}
Ajouter une clé déjà existante
Si tu appelles Add pour une clé déjà présente, tu prends une ArgumentException. Si tu veux «ajouter ou mettre à jour», utilise l’indexeur :
// Ajoute si absent, met à jour si présent
myDictionary["Murka"] = new Cat("Murka", 5);
Parcourir et modifier
N’essaie pas de modifier le dico (genre supprimer des éléments) direct dans une boucle foreach : tu vas te prendre une exception. Si tu veux supprimer des trucs, commence par lister les clés à virer, puis supprime-les dans une autre boucle :
// Façon safe de supprimer des éléments
var keysToRemove = new List<string>();
foreach (var pair in myDictionary)
{
if (pair.Value.Age > 10) // Condition pour supprimer
{
keysToRemove.Add(pair.Key);
}
}
foreach (var key in keysToRemove)
{
myDictionary.Remove(key);
}
GO TO FULL VERSION