Chargement...

Référence collections

En C#, les collections de référence constituent un élément fondamental pour la gestion et la manipulation efficace des données en mémoire. Contrairement aux types valeur, les collections de référence stockent des objets dans le heap, permettant une gestion dynamique et flexible des données. Elles sont essentielles pour les applications modernes nécessitant le stockage, l’accès et le traitement d’ensembles de données complexes. L'utilisation appropriée des collections de référence, telles que List, Dictionary\, Queue, Stack et HashSet, optimise la performance des applications tout en maintenant une architecture claire et extensible.
Les collections de référence en C# s'intègrent parfaitement avec les concepts clés du langage, incluant la syntaxe C# stricte, les structures de données avancées, les algorithmes optimisés et les principes de la programmation orientée objet (POO). Elles permettent de résoudre des problèmes variés, depuis le tri et la recherche jusqu’à la gestion de flux de données en temps réel dans des architectures logicielles complexes. Maîtriser ces collections est crucial pour concevoir des applications robustes, éviter les fuites mémoire et garantir une manipulation efficace des ressources.
Dans ce guide, vous apprendrez à créer, manipuler et optimiser les collections de référence en C#, à comprendre leurs performances et leurs limites, et à appliquer les meilleures pratiques pour les projets professionnels. Vous découvrirez également comment ces collections s’intègrent dans des modèles de conception, favorisant une architecture scalable et maintenable. Ce contenu est conçu pour renforcer votre capacité à résoudre des problèmes complexes en C# et à prendre des décisions éclairées sur l’utilisation des structures de données dans des systèmes réels.

Exemple de Base

text
TEXT Code
using System;
using System.Collections.Generic;

namespace ReferenceCollectionsExample
{
class Program
{
static void Main(string\[] args)
{
// Création d'une liste de chaînes
List<string> fruits = new List<string> { "Pomme", "Banane", "Cerise" };

// Ajout d'un élément
fruits.Add("Orange");

// Accès et modification
fruits[1] = "Mangue";

// Parcours de la collection
Console.WriteLine("Liste des fruits:");
foreach (string fruit in fruits)
{
Console.WriteLine(fruit);
}

// Recherche d'un élément
if (fruits.Contains("Cerise"))
{
Console.WriteLine("Cerise est présente dans la liste.");
}
}
}

}

L’exemple ci-dessus illustre l’utilisation de collections de référence avec List, l’une des collections les plus couramment utilisées en C#. La ligne List fruits = new List { "Pomme", "Banane", "Cerise" }; crée une liste stockée dans le heap, permettant l’ajout dynamique d’éléments sans contraintes de taille fixe. La méthode Add() montre comment insérer un nouvel élément tout en maintenant l’ordre de la collection. La modification d’un élément via l’index, fruits[1] = "Mangue";, démontre l’accès direct et la mise à jour efficace d’objets dans la collection.
Le foreach parcourt chaque élément de manière sécurisée, évitant les erreurs d’index et favorisant une syntaxe claire et lisible. L’appel à fruits.Contains("Cerise") montre un exemple simple de recherche dans une collection, utilisant un algorithme interne optimisé pour List. Ce code intègre également les meilleures pratiques : aucune fuite mémoire possible grâce à la gestion automatique du garbage collector, et manipulation sécurisée des données avec des types génériques, évitant les conversions de type coûteuses et les exceptions.
Dans un contexte réel, ces concepts permettent de gérer des ensembles de données dynamiques, tels que des listes d’utilisateurs, des commandes ou des événements. L’exemple met en évidence l’importance des collections de référence pour la POO en C#, car chaque élément est un objet, pouvant encapsuler des propriétés et des méthodes, facilitant ainsi la conception de systèmes modulaires et maintenables.

Exemple Pratique

text
TEXT Code
using System;
using System.Collections.Generic;

namespace AdvancedReferenceCollections
{
class Person
{
public string Name { get; set; }
public int Age { get; set; }
}

class Program
{
static void Main(string[] args)
{
// Création d'un dictionnaire pour stocker des objets Person avec un identifiant unique
Dictionary<int, Person> people = new Dictionary<int, Person>();

people.Add(1, new Person { Name = "Alice", Age = 30 });
people.Add(2, new Person { Name = "Bob", Age = 25 });
people.Add(3, new Person { Name = "Charlie", Age = 35 });

// Recherche d'une personne par clé
if (people.TryGetValue(2, out Person foundPerson))
{
Console.WriteLine($"Personne trouvée: {foundPerson.Name}, {foundPerson.Age} ans");
}

// Parcours du dictionnaire
foreach (var entry in people)
{
Console.WriteLine($"ID: {entry.Key}, Nom: {entry.Value.Name}");
}

// Suppression sécurisée d'une entrée
people.Remove(3);
}
}

}

Advanced C# Implementation

text
TEXT Code
using System;
using System.Collections.Generic;
using System.Linq;

namespace EnterpriseCollections
{
class Product
{
public string Name { get; set; }
public decimal Price { get; set; }
}

class Program
{
static void Main(string[] args)
{
try
{
// Création d'un HashSet pour éviter les doublons
HashSet<Product> products = new HashSet<Product>(new ProductComparer())
{
new Product { Name = "Laptop", Price = 1200 },
new Product { Name = "Tablet", Price = 450 },
new Product { Name = "Laptop", Price = 1200 } // sera ignoré
};

// Utilisation de LINQ pour filtrer et trier
var expensiveProducts = products
.Where(p => p.Price > 500)
.OrderByDescending(p => p.Price)
.ToList();

foreach (var product in expensiveProducts)
{
Console.WriteLine($"Produit: {product.Name}, Prix: {product.Price}");
}
}
catch (Exception ex)
{
Console.WriteLine($"Erreur: {ex.Message}");
}
}
}

class ProductComparer : IEqualityComparer<Product>
{
public bool Equals(Product x, Product y)
{
return x.Name == y.Name && x.Price == y.Price;
}

public int GetHashCode(Product obj)
{
return obj.Name.GetHashCode() ^ obj.Price.GetHashCode();
}
}

}

Les exemples pratiques démontrent des concepts avancés des collections de référence en C#. Le dictionnaire (Dictionary\) permet d’associer des clés uniques à des objets, facilitant les recherches rapides via TryGetValue, ce qui est essentiel pour les applications nécessitant un accès direct aux données. Le HashSet, illustré dans l’implémentation avancée, empêche les doublons et s’intègre avec LINQ pour filtrer, trier et transformer les collections efficacement. L’usage de ProductComparer montre comment personnaliser la comparaison des objets pour garantir l’intégrité des données dans les structures de référence.
Ces exemples abordent également les bonnes pratiques : gestion des exceptions via try-catch pour éviter les plantages, utilisation de types génériques pour un typage sûr, et application d’algorithmes LINQ pour optimiser les opérations sur les collections. Les développeurs doivent également considérer la performance en choisissant la structure appropriée (List pour l’ordre et l’accès indexé, Dictionary\ pour l’accès rapide par clé, HashSet pour les collections uniques).
En pratique, ces concepts s’appliquent à la manipulation de données en mémoire, à la conception de systèmes modulaires et à l’implémentation de modèles de conception tels que Repository ou Observer. Comprendre et maîtriser ces collections permet de résoudre efficacement des problèmes complexes, de maintenir une architecture performante et de minimiser les risques de fuites mémoire ou d’erreurs de logique.

C# best practices and common pitfalls

text
TEXT Code
// Best practices et pièges courants

* Utiliser des collections génériques pour éviter les conversions de type coûteuses et les exceptions
* Choisir la structure de données adaptée selon les besoins : List<T>, Dictionary\<TKey,TValue>, Queue<T>, Stack<T>, HashSet<T>
* Toujours gérer les exceptions lors des manipulations de collections pour éviter les plantages
* Préférer l’utilisation de foreach pour le parcours sécurisé des collections
* Éviter les boucles imbriquées inutiles pour optimiser les performances
* Utiliser LINQ avec parcimonie et optimiser les requêtes pour de grandes collections
* Supprimer les références aux objets inutilisés pour permettre au garbage collector de libérer la mémoire
* Tester les performances avec des collections volumineuses pour détecter les goulets d’étranglement
* Assurer la sécurité des données lors de l’accès concurrent aux collections (Collections.Concurrent si nécessaire)
* Préférer les comparateurs personnalisés pour HashSet ou Dictionary afin de garantir l’unicité et l’intégrité des données

📊 Référence Complète

C# Element/Method Description Syntax Example Notes
List<T> Collection dynamique ordonnée List<int> numbers = new List<int>(); numbers.Add(10); Accès indexé, redimensionnement automatique
List<T>.Add() Ajoute un élément à la liste numbers.Add(10); numbers.Add(5); Complexité O(1) en moyenne
List<T>.Remove() Supprime un élément numbers.Remove(10); numbers.Remove(5); Retourne true si supprimé
List<T>.Contains() Vérifie la présence d’un élément numbers.Contains(10); bool exists = numbers.Contains(5); Recherche linéaire
List<T>.Count Nombre d’éléments numbers.Count int total = numbers.Count; Lecture seule, actualisé dynamiquement
Dictionary\<TKey,TValue> Collection clé-valeur Dictionary\<int,string> dict = new Dictionary\<int,string>(); dict.Add(1,"Alice"); Accès rapide par clé
Dictionary\<TKey,TValue>.Add() Ajoute une paire clé-valeur dict.Add(1,"Alice"); dict.Add(2,"Bob"); Lève une exception si clé existe
Dictionary\<TKey,TValue>.TryGetValue() Récupère la valeur en toute sécurité dict.TryGetValue(2,out string val); bool found = dict.TryGetValue(1,out string name); Evite les exceptions de clé inexistante
Dictionary\<TKey,TValue>.Remove() Supprime une paire clé-valeur dict.Remove(1); dict.Remove(2); Retourne true si supprimé
Dictionary\<TKey,TValue>.Keys Collection des clés var keys = dict.Keys; foreach(var key in dict.Keys) Lecture seule
Dictionary\<TKey,TValue>.Values Collection des valeurs var values = dict.Values; foreach(var val in dict.Values) Lecture seule
Queue<T> FIFO collection Queue<int> q = new Queue<int>(); q.Enqueue(10); First In First Out
Queue<T>.Enqueue() Ajoute à la queue q.Enqueue(10); q.Enqueue(20) O(1)
Queue<T>.Dequeue() Retire de la queue q.Dequeue(); int first = q.Dequeue(); O(1), exception si vide
Queue<T>.Peek() Accède au premier élément sans retirer q.Peek(); int peek = q.Peek(); Exception si vide
Stack<T> LIFO collection Stack<int> s = new Stack<int>(); s.Push(10); Last In First Out
Stack<T>.Push() Ajoute au sommet s.Push(10); s.Push(20) O(1)
Stack<T>.Pop() Retire du sommet s.Pop(); int top = s.Pop(); O(1), exception si vide
Stack<T>.Peek() Accède au sommet sans retirer s.Peek(); int top = s.Peek(); Exception si vide
HashSet<T> Collection unique HashSet<int> hs = new HashSet<int>(); hs.Add(10); Évite les doublons
HashSet<T>.Add() Ajoute un élément hs.Add(10); hs.Add(5); Retourne false si déjà présent
HashSet<T>.Remove() Supprime un élément hs.Remove(10); hs.Remove(5); Retourne true si supprimé
HashSet<T>.Contains() Vérifie la présence hs.Contains(10); bool exists = hs.Contains(5); O(1) en moyenne
IEnumerable<T> Interface de parcours IEnumerable<int> numbers foreach(var n in numbers) Base pour foreach et LINQ
ICollection<T> Interface de collection ICollection<int> coll coll.Count Supporte Count, Add, Remove
IList<T> Interface de liste IList<int> list list\[0] = 10 Accès indexé
IReadOnlyCollection<T> Lecture seule IReadOnlyCollection<int> readOnly int total = readOnly.Count Pas de modification
IReadOnlyList<T> Lecture seule indexée IReadOnlyList<int> readOnlyList int first = readOnlyList\[0] Lecture seule
ObservableCollection<T> Collection avec notification ObservableCollection<int> oc = new ObservableCollection<int>(); oc.CollectionChanged += Handler Utile pour MVVM
ConcurrentDictionary\<TKey,TValue> Thread-safe dictionnaire ConcurrentDictionary\<int,string> cd = new ConcurrentDictionary\<int,string>(); cd.TryAdd(1,"A"); Sécurisé multi-thread
ConcurrentQueue<T> Thread-safe queue ConcurrentQueue<int> cq = new ConcurrentQueue<int>(); cq.TryDequeue(out int val); FIFO multi-thread
ConcurrentStack<T> Thread-safe stack ConcurrentStack<int> cs = new ConcurrentStack<int>(); cs.TryPop(out int val); LIFO multi-thread
SortedList\<TKey,TValue> Dictionnaire trié par clé SortedList\<int,string> sl = new SortedList\<int,string>(); sl.Add(1,"A"); Tri automatique
SortedDictionary\<TKey,TValue> Dictionnaire trié SortedDictionary\<int,string> sd = new SortedDictionary\<int,string>(); sd.Add(1,"A"); Plus performant pour insertions fréquentes
LinkedList<T> Liste doublement chaînée LinkedList<int> ll = new LinkedList<int>(); ll.AddLast(10); Accès séquentiel
LinkedList<T>.AddFirst() Ajoute en début ll.AddFirst(5); ll.AddFirst(1) O(1)
LinkedList<T>.AddLast() Ajoute à la fin ll.AddLast(10); ll.AddLast(20) O(1)
LinkedList<T>.Remove() Supprime un élément ll.Remove(10); ll.Remove(20) O(n)
LinkedList<T>.Find() Recherche un élément ll.Find(10); var node = ll.Find(10) Retourne LinkedListNode<T>
Stack<T>.Clear() Vide la pile s.Clear(); s.Clear() Libère références
Queue<T>.Clear() Vide la queue q.Clear(); q.Clear() Libère références
List<T>.Clear() Vide la liste numbers.Clear(); numbers.Clear() Libère références
Dictionary\<TKey,TValue>.Clear() Vide le dictionnaire dict.Clear(); dict.Clear() Libère références
List<T>.IndexOf() Retourne l’index numbers.IndexOf(5); int idx = numbers.IndexOf(5) -1 si absent
ArrayList Collection non générique ArrayList arr = new ArrayList(); arr.Add(10); Legacy, éviter en C# moderne
Queue<T>.Contains() Vérifie la présence q.Contains(10); bool exists = q.Contains(5) O(n)
Stack<T>.Contains() Vérifie la présence s.Contains(10); bool exists = s.Contains(5) O(n)
HashSet<T>.UnionWith() Union de collections hs1.UnionWith(hs2); hs1.UnionWith(hs2) Mutatif
HashSet<T>.IntersectWith() Intersection hs1.IntersectWith(hs2); hs1.IntersectWith(hs2) Mutatif
HashSet<T>.ExceptWith() Différence hs1.ExceptWith(hs2); hs1.ExceptWith(hs2) Mutatif
HashSet<T>.SymmetricExceptWith() Différence symétrique hs1.SymmetricExceptWith(hs2); hs1.SymmetricExceptWith(hs2) Mutatif
Dictionary\<TKey,TValue>.ContainsKey() Vérifie la clé dict.ContainsKey(1); bool exists = dict.ContainsKey(2) O(1)
Dictionary\<TKey,TValue>.ContainsValue() Vérifie la valeur dict.ContainsValue("Alice"); bool exists = dict.ContainsValue("Bob") O(n)
Queue<T>.TryPeek() Lecture sécurisée q.TryPeek(out int val); bool ok = q.TryPeek(out val) Évite exceptions
Stack<T>.TryPeek() Lecture sécurisée s.TryPeek(out int val); bool ok = s.TryPeek(out val) Évite exceptions
Stack<T>.TryPop() Retrait sécurisé s.TryPop(out int val); bool ok = s.TryPop(out val) Évite exceptions
Queue<T>.TryDequeue() Retrait sécurisé q.TryDequeue(out int val); bool ok = q.TryDequeue(out val) Évite exceptions
List<T>.Insert() Insère à un index numbers.Insert(1, 99); numbers.Insert(0,10) Décalage des éléments
List<T>.RemoveAt() Supprime par index numbers.RemoveAt(1); numbers.RemoveAt(0) Décalage des éléments
Dictionary\<TKey,TValue>.Count Nombre de paires dict.Count int total = dict.Count Lecture seule
HashSet<T>.Count Nombre d’éléments uniques hs.Count int total = hs.Count Lecture seule
Queue<T>.Count Nombre d’éléments q.Count int total = q.Count Lecture seule
Stack<T>.Count Nombre d’éléments s.Count int total = s.Count Lecture seule
SortedList\<TKey,TValue>.Count Nombre d’éléments sl.Count int total = sl.Count Lecture seule
LinkedList<T>.Count Nombre d’éléments ll.Count int total = ll.Count Lecture seule
ObservableCollection<T>.Count Nombre d’éléments oc.Count int total = oc.Count Lecture seule
ConcurrentDictionary\<TKey,TValue>.Count Nombre d’éléments cd.Count int total = cd.Count Lecture seule
Nombre d’éléments cq.Count int total = cq.Count Lecture seule
ConcurrentStack<T>.Count Nombre d’éléments cs.Count int total = cs.Count Lecture seule
List<T>.Find() Recherche un élément numbers.Find(x => x > 5); int found = numbers.Find(n => n==5) Retourne l’élément ou défaut
List<T>.FindAll() Recherche multiple numbers.FindAll(x => x>5); var results = numbers.FindAll(n => n>10) Retourne List<T>
List<T>.Sort() Tri de la liste numbers.Sort(); numbers.Sort(); Utilise QuickSort interne
List<T>.Reverse() Inverse la liste numbers.Reverse(); numbers.Reverse(); In-place
List<T>.ToArray() Conversion en tableau numbers.ToArray(); int\[] arr = numbers.ToArray(); Copie
List<T>.ForEach() Parcours avec action numbers.ForEach(n => Console.WriteLine(n)); numbers.ForEach(n=>Console.WriteLine(n)); Expression lambda
List<T>.Exists() Vérifie condition numbers.Exists(n => n>5); bool exists = numbers.Exists(n=>n>10) Retourne bool
Dictionary\<TKey,TValue>.Clear() Vide le dictionnaire dict.Clear(); dict.Clear(); Supprime toutes paires
List<T>.AddRange() Ajoute plusieurs éléments numbers.AddRange(new List<int>{1,2}); numbers.AddRange(new List<int>{3,4}); O(n)
Queue<T>.Clear() Vide la queue q.Clear(); q.Clear() Libère références
Stack<T>.Clear() Vide la pile s.Clear(); s.Clear() Libère références
HashSet<T>.Clear() Vide le HashSet hs.Clear(); hs.Clear() Libère références
LinkedList<T>.Clear() Vide la liste chaînée ll.Clear(); ll.Clear() Libère références
ObservableCollection<T>.Clear() Vide la collection oc.Clear(); oc.Clear() Notifie les abonnés
ConcurrentDictionary\<TKey,TValue>.Clear() Vide le dictionnaire cd.Clear(); cd.Clear() Thread-safe
ConcurrentQueue<T>.Clear() Vide la queue cq.Clear(); cq.Clear() Thread-safe
ConcurrentStack<T>.Clear() Vide la pile cs.Clear(); cs.Clear() Thread-safe

📊 Complete C# Properties Reference

Property Values Default Description C# Support
Count int 0 Nombre d’éléments dans la collection All C# collections
Capacity int 4 Nombre d’éléments que la collection peut contenir avant redimensionnement automatique List<T>
IsReadOnly bool false Indique si la collection est en lecture seule ICollection<T>, IList<T>
Keys TKey collection N/A Retourne les clés d’un dictionnaire Dictionary\<TKey,TValue>
Values TValue collection N/A Retourne les valeurs d’un dictionnaire Dictionary\<TKey,TValue>
Comparer IEqualityComparer Default comparer Comparateur utilisé pour HashSet ou Dictionary HashSet<T>, Dictionary\<TKey,TValue>
SyncRoot object null Objet pour synchronisation multi-thread ICollection
IsSynchronized bool false Indique si la collection est thread-safe ICollection
CountChanged Event N/A Événement déclenché lors du changement de Count ObservableCollection<T>
CollectionChanged Event N/A Événement déclenché lors d’une modification ObservableCollection<T>
IsFixedSize bool false Indique si la taille est fixe ArrayList, IList
Capacity int 0 Capacité maximale actuelle de la collection ArrayList

La maîtrise des collections de référence en C# offre un contrôle avancé sur la gestion des données et la conception des systèmes. Vous avez appris à manipuler des listes, dictionnaires, files, piles et ensembles uniques, à utiliser LINQ pour transformer et filtrer les données et à gérer les exceptions pour une sécurité et une performance optimales. Ces compétences permettent de construire des applications modulaires, performantes et maintenables, en intégrant les principes de la POO et les bonnes pratiques C#.
Les prochaines étapes incluent l’étude des collections concurrentes, l’optimisation des algorithmes de tri et de recherche, ainsi que l’intégration de ces collections dans des patterns de conception tels que Repository ou Observer. Il est recommandé d’expérimenter avec des collections volumineuses pour mesurer les performances et comprendre l’impact des choix de structure sur l’architecture logicielle. Pour approfondir vos connaissances, explorez la documentation officielle Microsoft, les articles sur LINQ et les ressources avancées sur les structures de données en C#. Appliquer ces concepts dans des projets réels consolide votre expertise et prépare à développer des systèmes d’entreprise robustes et évolutifs.

🧠 Testez Vos Connaissances

Prêt à Commencer

Test Your Knowledge

Test your understanding of this topic with practical questions.

4
Questions
🎯
70%
Pour Réussir
♾️
Temps
🔄
Tentatives

📝 Instructions

  • Lisez chaque question attentivement
  • Sélectionnez la meilleure réponse pour chaque question
  • Vous pouvez refaire le quiz autant de fois que vous le souhaitez
  • Votre progression sera affichée en haut