Les collections génériques en Csharp.Net

 Outre le tableau, il existe diverses classes pour stocker des collections d'éléments. Il existe des versions génériques dans l'espace de
noms System.Collections.Generic et des versions non génériques dans System.Collections. Nous présenterons deux collections génériques
fréquemment utilisées : la liste et le dictionnaire.

La liste des collections génériques est la suivante :
liste des collections génériques
 3.4.1 La classe générique List<T>
La classe System.Collections.Generic.List<T> permet d'implémenter des collections d'objets de type T dont la taille varie au cours de
l'exécution du programme. Un objet de type List<T> se manipule presque comme un tableau. Ainsi l'élément i d'une liste l est-il
noté l[i].
Il existe également un type de liste non générique :  ArrayList  capable de stocker des références sur des objets quelconques.
ArrayList est fonctionnellement équivalente à List<Object>. Un objet ArrayList ressemble à ceci :
La classe générique List

 Ci-dessus, les éléments 0, 1 et i de la liste pointent sur des objets de types différents. Il faut qu'un objet soit d'abord créé avant
d'ajouter sa référence à la liste ArrayList. Bien qu'un ArrayList stocke des références d'objet, il est possible d'y stocker des nombres.
Cela se fait par un mécanisme appelé Boxing : le nombre est encapsulé dans un objet O de type Object et c'est la référence O qui est
stocké dans la liste.  C'est un mécanisme transparent pour le développeur. On peut ainsi écrire :
ArrayList liste=new ArrayList();
liste.Add(4);
Cela produira le résultat suivant :
La classe générique List
Ci-dessus, le nombre 4 a été encapsulé dans un objet O et la référence O est mémorisée dans la liste. Pour le récupérer, on pourra
écrire :
int i = (int)liste[0];
L'opération Object -> int est appelée Unboxing. Si une liste est entièrement composée de types int, la déclarer comme List<int>
améliore les performances. En effet, les nombres de type int sont alors stockés dans la liste elle-même et non dans des types Object
extérieurs à la liste. Les opérations Boxing / Unboxing n'ont plus lieu.

Les collections génériques en Csharp.Net
Pour un objet List<T> ou T est une classe, la liste stocke là encore les références des objets de type T :

Voici quelques-unes des propriétés et méthodes des listes génériques :
Propriétés
public int Count {get;} nombre d'éléments de la liste

public int Capacity {get;} nombre d'éléments que la liste peut contenir avant d'être redimensionnée. Ce
redimensionnement se fait automatiquement. Cette notion de capacité de liste
est analogue à celle de capacité décrite pour la classe StringBuilder page 95.
Méthodes
public void Add(T item) ajoute item à la liste
public int BinarySearch<T>(T item) rend la position de item dans la liste s'il s'y
trouve sinon un nombre <0
public int BinarySearch<T>(T item, IComparer<T>
comparateur)
idem mais le 2ième paramètre permet de comparer deux
éléments de la liste. L'interface IComparer<T> a été
présentée page 81.
public void Clear() supprime tous les éléments de la liste
public bool Contains(T item) rend True si item est dans la liste, False sinon
public void CopyTo(T[] tableau) copie les éléments de la liste dans tableau.
public int IndexOf(T item) rend la position de item dans tableau ou -1 si
valeur n'est pas trouvée.
public void Insert(T item, int index) insère item à la position index de la liste
public bool Remove(T item) supprime item de la liste. Rend True si l'opération
réussit, False sinon.
public void RemoveAt(int index) supprime l'élément n° index de la liste
public void Sort(IComparer<T> comparateur) trie la liste selon un ordre défini par comparateur.
Cette méthode a été présentée page 81.
public void Sort() trie la liste selon l'ordre défini par le type des
éléments de la liste
public T[] ToArray() rend les éléments de la liste sous forme de tableau
Reprenons l'exemple traité précédemment avec un objet de type Array et traitons-le maintenant avec un objet de type List<T>.
Parce que la liste est un objet proche du tableau, le code change peu. Nous ne présentons que les modifications notables :

1. using System;
2. using System.Collections.Generic;
3.
4. namespace Chap3 {
5. class Program {
6. // type de recherche
7. enum TypeRecherche { linéaire, dichotomique };
8.
9. // méthode principale
10. static void Main(string[] args) {
11. // lecture des éléments d'une liste tapés au clavier
12. List<double> éléments;
13. Saisie(out éléments);
14. // nombre d'éléments
15. Console.WriteLine("La liste a {0} éléments et une capacité de {1} éléments",
éléments.Count, éléments.Capacity);
16. // affichage liste non triée
17. Affiche("Liste non triée", éléments);
18. // Recherche linéaire dans la liste non triée
19. Recherche(éléments, TypeRecherche.linéaire);
20. // tri de la liste
21. éléments.Sort();
22. // affichage liste triée
23. Affiche("Liste triée", éléments);
24. // Recherche dichotomique dans la liste triée
25. Recherche(éléments, TypeRecherche.dichotomique);
26. }
27.
28. // saisie des valeurs de la liste éléments
29. // éléments : référence sur la liste créée par la méthode
30. static void Saisie(out List<double> éléments) {
31....
32. // au départ, la liste est vide
33. éléments = new List<double>();
34. // boucle de saisie des éléments de la liste
35. while (!terminé) {
36....
37. // si pas d'erreur
38. if (!erreur) {
39. // un élément de plus dans la liste
40. éléments.Add(élément);
41. }
42. }//while
43. }
44.
 45. // méthode générique pour afficher les éléments d'un objet énumérable
46. static void Affiche<T>(string texte, IEnumerable<T> éléments) {
47. Console.WriteLine(texte.PadRight(50, '-'));
48. foreach (T élément in éléments) {
49. Console.WriteLine(élément);
50. }
51. }
52.
53. // recherche d'un élément dans la liste
54. // éléments : liste de réels
55. // TypeRecherche : dichotomique ou linéaire
56. static void Recherche(List<double> éléments, TypeRecherche type) {
57....
58. while (!terminé) {
59....
60. // si pas d'erreur
61. if (!erreur) {
62. // on cherche l'élément dans la liste
63. if (type == TypeRecherche.dichotomique)
64. // recherche dichotomique
65. i = éléments.BinarySearch(élément);
66. else
67. // recherche linéaire
68. i = éléments.IndexOf(élément);
69. // Affichage réponse
70....
71. }//if
72. }//while
73. }
74. }
75.}
• lignes 46-51 : la méthode générique Affiche<T> admet deux paramètres :
• le 1er paramètre est un texte à écrire
• le 2ième paramètre est un objet implémentant l'interface générique IEnumerable<T> :
1. public interface IEnumerable<T>{
2. IEnumerator GetEnumerator();
3. IEnumerator<T> GetEnumerator();
4. }
La structure foreach( T élément in éléments) de la ligne 48, est valide pour tout objet éléments implémentant l'interface IEnumerable. Les
tableaux (Array) et les listes (List<T>) implémentent l'interface IEnumerable<T>. Aussi la méthode Affiche convient-elle aussi bien
pour afficher des tableaux que des listes.
Les résultats d'exécution du programme sont les mêmes que dans l'exemple utilisant la classe Array.
3.4.2 La classe Dictionary<TKey,TValue>
La classe  System.Collections.Generic.Dictionary<TKey,TValue>    permet d'implémenter un dictionnaire. On peut voir un dictionnaire
comme un tableau à deux colonnes :
clé valeur
clé1 valeur1
clé2 valeur2
.. ...
Dans la classe Dictionary<TKey,TValue> les clés sont de type Tkey, les valeurs de type TValue. Les clés sont uniques, c.a.d. qu'il ne
peut y avoir deux clés identiques. Un tel dictionnaire pourrait ressembler à ceci si les types TKey et TValue désignaient des classes :
La classe Dictionary TKey,TValue
 La valeur associée à la clé C d'un dictionnaire D est obtenue par la notation D[C]. Cette valeur est en lecture et écriture. Ainsi on
peut écrire :
1. TValue v=...;
2. TKey c=...;
3. Dictionary<TKey,TValue> D=new Dictionary<TKey,TValue>();
4. D[c]=v;
5. v=D[c];
Si la clé c n'existe pas dans le dictionnaire D, la notation D[c] lance une exception.
Les méthodes et propriétés principales de la classe Dictionary<TKey,TValue> sont les suivantes :
Constructeurs
public Dictionary<TKey,TValue>() constructeur sans paramètres - construit un dictionnaire vide. Il
existe plusieurs autres constructeurs.
Propriétés
public int Count {get;} nombre d'entrées (clé, valeur) dans le dictionnaire
public Dictionary<TKey,TValue>.KeyCollection Keys
{get;}
collection des clés du dictionnaire.
public Dictionary<TKey,TValue>.ValueCollection
Values {get;}
collection des valeurs du dictionnaire.
Méthodes
public void Add(TKey key, TValue value) ajoute le couple (key, value) au dictionnaire
public void Clear() supprime tous les couples du dictionnaire
public bool ContainsKey (TKey key) rend True si key est une clé du dictionnaire, False
sinon
public bool ContainsValue (TValue value) rend True si value est une valeur du dictionnaire,
False sinon
public void CopyTo(T[] tableau) copie les éléments de la liste dans tableau.
public bool Remove(TKey key) supprime du dictionnaire le couple de clé key. Rend
True si l'opération réussit, False sinon.
public bool TryGetValue(TKey key,out TValue value) rend dans value, la valeur associée à la clé key si
cette dernière existe, sinon rend la valeur par
défaut du type TValue (0 pour les nombres, false
pour les booléens, null pour les références d'objet)
Considérons le programme exemple suivant :
1. using System;
2. using System.Collections.Generic;
3.
4. namespace Chap3 {
5. class Program {
6. static void Main(string[] args) {
7. // création d'un dictionnaire <string,int>
8. string[] liste = { "jean:20", "paul:18", "mélanie:10", "violette:15" };
9. string[] champs = null;
10. char[] séparateurs = new char[] { ':' };
11. Dictionary<string,int> dico = new Dictionary<string,int>();
12. for (int i = 0; i <liste.Length; i++) {
13. champs = liste[i].Split(séparateurs);
14. dico[champs[0]]= int.Parse(champs[1]);
15. }//for
16. // nbre d'éléments dans le dictionnaire
17. Console.WriteLine("Le dictionnaire a " + dico.Count + " éléments");
18. // liste des clés
19. Affiche("[Liste des clés]",dico.Keys);
20. // liste des valeurs
21. Affiche("[Liste des valeurs]", dico.Values);
22. // liste des clés & valeurs
23. Console.WriteLine("[Liste des clés & valeurs]");
24. foreach (string clé in dico.Keys) {
25. Console.WriteLine("clé=" + clé + " valeur=" + dico[clé]);
26. }
27. // on supprime la clé "paul"
28. Console.WriteLine("[Suppression d'une clé]");
29. dico.Remove("paul");
30. // liste des clés & valeurs
31. Console.WriteLine("[Liste des clés & valeurs]");
32. foreach (string clé in dico.Keys) {
33. Console.WriteLine("clé=" + clé + " valeur=" + dico[clé]);
34. }
35. // recherche dans le dictionnaire
36. String nomCherché = null;
37. Console.Write("Nom recherché (rien pour arrêter) : ");
38. nomCherché = Console.ReadLine().Trim();
39. int value;
40. while (!nomCherché.Equals("")) {
41. dico.TryGetValue(nomCherché, out value);
42. if (value!=0) {
43. Console.WriteLine(nomCherché + "," + value);
44. } else {
45. Console.WriteLine("Nom " + nomCherché + " inconnu");
46. }
47. // recherche suivante
48. Console.Out.Write("Nom recherché (rien pour arrêter) : ");
49. nomCherché = Console.ReadLine().Trim();
50. }//while
51. }
52.
53. // méthode générique pour afficher les éléments d'un type énumérable
54. static void Affiche<T>(string texte, IEnumerable<T> éléments) {
55. Console.WriteLine(texte.PadRight(50, '-'));
56. foreach (T élément in éléments) {
57. Console.WriteLine(élément);
58. }
59. }
60.
61. }
62.}
• ligne 8 : un tableau de string qui va servir à initialiser le dictionnaire <string,int>
• ligne 11 : le dictionnaire <string,int>
• lignes 12-15 : son initialisation à partir du tableau de string de la ligne 8
• ligne 17 : nombre d'entrées du dictionnaire
• ligne 19 : les clés du dictionnaire
• ligne 21 : les valeurs du dictionnaire
• ligne 29 : suppression d'une entrée du dictionnaire
• ligne 41 : recherche d'une clé dans le dictionnaire. Si elle n'existe pas, la méthode TryGetValue mettra 0 dans value, car value
est de type numérique. Cette technique n'est utilisable ici que parce qu'on sait que la valeur 0 n'est pas dans le dictionnaire.
Les résultats d'exécution sont les suivants :
1. Le dictionnaire a 4 éléments
2. [Liste des clés]----------------------------------
3. jean
4. paul
5. mélanie
6. violette
7. [Liste des valeurs]-------------------------------
8. 20
9. 18
10.10
11.15
12.[Liste des clés & valeurs]
13.clé=jean valeur=20
14.clé=paul valeur=18
15.clé=mélanie valeur=10
16.clé=violette valeur=15
17.[Suppression d'une clé]
18.[Liste des clés & valeurs]
19.clé=jean valeur=20
20.clé=mélanie valeur=10
21.clé=violette valeur=15
22.Nom recherché (rien pour arrêter) : violette
23.violette,15
24.Nom recherché (rien pour arrêter) : x
25.Nom x inconnu
Publié par Drupal french Study