✅ Questions & Réponses sur Dictionary en C#
1. Qu’est-ce qu’un Dictionary en C# ?
-
Réponse :
UnDictionary<TKey, TValue>est une collection générique de paires clé/valeur dans laquelle chaque clé est unique. Il permet un accès rapide aux valeurs en fonction de leur clé, grâce à un mécanisme de hachage.
2. Quelle est la complexité temporelle des opérations dans un Dictionary ?
-
Réponse :
En moyenne : -
Ajout (Add) : O(1)
-
Recherche (ContainsKey, indexeur
dict[key]) : O(1) -
Suppression (Remove) : O(1)
-
Dans le pire des cas (collision excessive) : O(n).
3. Quelle est la différence entre Dictionary et Hashtable ?
-
Réponse :
-
Dictionary<TKey, TValue>est générique (type-safe). -
Hashtableest non générique (stocke des objets, nécessite des cast). -
Dictionaryest généralement plus performant car il évite le boxing/unboxing. -
Dictionarypréserve l’ordre d’insertion à partir de .NET Core 3.0.
-
4. Comment vérifier si une clé existe dans un Dictionary ?
-
Réponse :
if (dict.ContainsKey("clé")) { ... }
ou
if (dict.TryGetValue("clé", out var value)) { ... }
👉 TryGetValue est préférable car il évite une double recherche.
5. Que se passe-t-il si on ajoute une clé déjà existante ?
-
Réponse :
-
Avec
dict.Add(key, value)→ exceptionArgumentException. -
Avec l’indexeur
dict[key] = value→ la valeur est mise à jour.
-
6. Quelle est la différence entre TryGetValue et l’indexeur dict[key] ?
-
Réponse :
-
dict[key]lève une exceptionKeyNotFoundExceptionsi la clé n’existe pas. -
TryGetValueretournefalsesi la clé n’existe pas, et affecteout valueà la valeur par défaut du type.
-
7. Comment parcourir un Dictionary ?
-
Réponse :
foreach (var kvp in dict)
{
Console.WriteLine($"{kvp.Key} : {kvp.Value}");
}
Ou uniquement les clés :
foreach (var key in dict.Keys) { ... }
Ou uniquement les valeurs :
foreach (var value in dict.Values) { ... }
8. Comment supprimer un élément dans un Dictionary ?
-
Réponse :
dict.Remove("clé");
Retourne true si la clé existait et a été supprimée.
9. Peut-on utiliser null comme clé dans un Dictionary ?
-
Réponse :
Non,Dictionaryne permet pasnullcomme clé (sauf siTKeyest nullable et que vous utilisez un comparer personnalisé).
En revanche, les valeurs peuvent êtrenull.
10. Comment personnaliser la comparaison des clés ?
-
Réponse :
En passant unIEqualityComparer<TKey>au constructeur duDictionary:
var dict = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
👉 Ici, les clés "Test" et "test" seront considérées comme identiques.
11. Quelle est la différence entre Dictionary et ConcurrentDictionary ?
-
Réponse :
-
Dictionaryn’est pas thread-safe → pas sûr pour un accès concurrent. -
ConcurrentDictionaryest conçu pour les environnements multithreads (lock interne optimisé). -
Exemple :
-
var concurrentDict = new ConcurrentDictionary<int, string>();
concurrentDict.TryAdd(1, "Hello");
12. Comment convertir un Dictionary en List ou en LINQ ?
-
Réponse :
var list = dict.ToList(); // List<KeyValuePair<TKey, TValue>>
Ou filtrer avec LINQ :
var filtered = dict.Where(kvp => kvp.Value.StartsWith("A"))
.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
13. Peut-on contrôler la capacité d’un Dictionary ?
-
Réponse :
Oui, avec le constructeur :
var dict = new Dictionary<int, string>(capacity: 100);
Cela améliore les performances si on connaît à l’avance la taille.
14. Qu’est-ce qu’une collision dans un Dictionary ?
-
Réponse :
Une collision se produit lorsque deux clés différentes génèrent le même code de hachage.
LeDictionaryles stocke alors dans une structure interne (liste chaînée ou buckets) et les distingue avecEquals.
15. Comment fusionner deux Dictionary ?
-
Réponse :
foreach (var kvp in dict2)
dict1[kvp.Key] = kvp.Value; // écrase si la clé existe
Ou en LINQ :
var merged = dict1.Concat(dict2)
.ToDictionary(kvp => kvp.Key, kvp => kvp.Value);
⚡️ Pièges fréquents sur Dictionary en C#
1. Que se passe-t-il si on fait dict["cléInexistante"] ?
-
Piège : Beaucoup pensent que ça retourne
null. -
Réponse : En réalité, ça lance une exception
KeyNotFoundException.
👉 La bonne pratique est d’utiliserTryGetValue.
2. Quelle est la différence entre dict.Add(k, v) et dict[k] = v ?
-
Piège : Certains pensent que c’est identique.
-
Réponse :
-
Add(k, v)lève une exception si la clé existe déjà. -
dict[k] = vécrase simplement la valeur existante.
-
3. L’ordre des éléments est-il garanti dans un Dictionary ?
-
Piège : Avant .NET Core 3.0, l’ordre d’énumération n’était pas garanti.
-
Réponse : Depuis .NET Core 3.0 et .NET 5+, l’ordre d’insertion est préservé.
👉 En entretien, il faut préciser "ça dépend de la version du framework".
4. Peut-on avoir deux clés différentes qui ont le même hash code ?
-
Piège : Beaucoup pensent que c’est impossible.
-
Réponse : Oui, c’est possible → c’est une collision.
LeDictionaryutilise à la foisGetHashCode()etEquals()pour distinguer les clés.
5. Que se passe-t-il si la clé est null ?
-
Piège : Certains pensent que
nullest accepté. -
Réponse : Non,
Dictionaryn’accepte pasnullcomme clé (sauf cas particulier avecNullable<T>et un comparer personnalisé).
👉 Par contre, les valeurs peuvent êtrenull.
6. Un Dictionary est-il thread-safe ?
-
Piège : Beaucoup pensent que oui car c’est une collection "haut niveau".
-
Réponse : Non,
Dictionaryn’est pas thread-safe.
Pour les scénarios multithread, il faut utiliserConcurrentDictionary.
7. Que se passe-t-il si on modifie un Dictionary pendant qu’on l’énumère ?
-
Piège : Certains pensent que ça met juste à jour l’énumération.
-
Réponse : Ça lance une exception
InvalidOperationException.
👉 Solution : utiliserToList()avant, ouConcurrentDictionary.
8. Quelle est la différence entre ContainsKey et ContainsValue ?
-
Piège : Certains pensent que les deux sont O(1).
-
Réponse :
-
ContainsKeyest O(1) en moyenne. -
ContainsValueest O(n) car il doit parcourir toutes les valeurs.
-
9. Un Dictionary peut-il contenir des doublons ?
-
Piège : Certains répondent "oui" en pensant aux valeurs.
-
Réponse :
-
Doublons de clés → impossible.
-
Doublons de valeurs → oui, autorisé.
-
10. Différence entre dict.Keys et dict.Values ?
-
Piège : Certains pensent que ce sont des copies.
-
Réponse : Ce sont des vues dynamiques (pas des copies).
Si on modifie le dictionnaire,dict.Keysetdict.Valuesse mettent à jour automatiquement.
11. Que se passe-t-il si la méthode GetHashCode() d’une clé change après insertion dans un Dictionary ?
-
Piège : Question avancée qui piège même des seniors.
-
Réponse : Si la clé est mutable et que son hash change, elle devient intraçable → impossible de la retrouver.
👉 Toujours utiliser des clés immuables (ex.string,int).
12. Peut-on comparer deux Dictionary directement avec == ou .Equals() ?
-
Piège : Certains pensent que ça compare les éléments.
-
Réponse : Non, ça compare uniquement les références.
👉 Pour comparer le contenu :
dict1.OrderBy(kvp => kvp.Key)
.SequenceEqual(dict2.OrderBy(kvp => kvp.Key));
13. Que vaut dict.Count si on supprime une clé inexistante ?
-
Piège : Certains pensent qu’une exception est levée.
-
Réponse :
Remove(key)retournefalse, etCountreste inchangé.
14. Un Dictionary est-il toujours plus rapide qu’une List pour chercher un élément ?
-
Piège : Réponse automatique "oui".
-
Réponse : En général oui (O(1) vs O(n)), mais :
-
Pour des petites collections (< 10 éléments), une
Listpeut être plus rapide à cause du surcoût du hachage. -
Les performances dépendent de la taille et du scénario.
-
🔎 Comment un Dictionary gère une collision ?
Un Dictionary est basé sur un tableau de buckets (seaux).
Quand on insère une clé :
-
Le hash code de la clé (
GetHashCode()) est calculé. -
Ce hash est transformé en un index de bucket (via modulo sur la capacité).
-
Si deux clés différentes donnent le même index, c’est une collision.
-
Le
Dictionarystocke alors les deux entrées dans une structure de liste chaînée interne (ou un tableau de "entries"). -
Lors de l’accès, il compare d’abord les hash codes, puis utilise
Equals()pour distinguer les clés.
✅ Exemple de collision
class BadKey
{
public string Value { get; set; }
// Mauvaise implémentation : toutes les clés ont le même hash !
public override int GetHashCode() => 42;
public override bool Equals(object obj)
=> obj is BadKey other && Value == other.Value;
}
var dict = new Dictionary<BadKey, string>();
dict[new BadKey { Value = "A" }] = "Alpha";
dict[new BadKey { Value = "B" }] = "Bravo";
Console.WriteLine(dict.Count); // 2 (collision interne gérée)
👉 Ici, toutes les clés tombent dans le même bucket, mais grâce à Equals(), le Dictionary fait la distinction.
🚀 Bonnes pratiques pour éviter / bien gérer les collisions
-
Toujours surcharger
GetHashCode()etEquals()de manière cohérente :-
Deux objets égaux (
Equals == true) doivent avoir le même hash code. -
Mais deux objets différents peuvent avoir le même hash (collision tolérée).
-
-
Utiliser des clés immuables (comme
string,int,Guid) → évite que le hash change après insertion. -
Utiliser un
IEqualityComparer<TKey>personnalisé si nécessaire :
Exemple avec un comparer insensible à la casse :var dict = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase); dict["Test"] = "Hello"; Console.WriteLine(dict.ContainsKey("test")); // True -
Éviter les hash codes constants ou mal répartis → sinon toutes les clés se retrouvent dans le même bucket, et les performances tombent de O(1) à O(n).
⚡ Question piège en entretien
👉 "Que se passe-t-il si toutes les clés d’un Dictionary ont le même hash code ?"
-
Réponse attendue :
LeDictionarycontinue de fonctionner correctement (grâce àEquals), mais les performances chutent car toutes les recherches se font dans une liste chaînée interne → donc complexité O(n) au lieu de O(1).
Aucun commentaire:
Enregistrer un commentaire