Les collections génériques sous .NET 2.0
[50 mn de lecture - paru le 5/18/2006 9:26:20 PM - Public : Confirmé]
|
   
|
Auteur
3 Les listes
3.1 IntroductionUne liste est un conteneur fortement typé d'objets accessibles par index. La liste fournit des méthodes de recherche, de tri et de manipulation. Une liste est la forme générique d'une ArrayList. Elle implémente les interfaces IEnumerable, ICollection et IList.
3.2 L'interface IListL'interface IList est implémentée par les listes.
Elle étends les membres de ICollection de :
- IndexOf(T idem) : retourne l'index de l'objet item.
- Insert(int index, T item) : ajoute à l'index l'objet item.
- RemoveAt(int index) : supprime l'objet à partir de son index.
- T this[int index] : accesseur en get/set de l'objet à partir de son index.
3.3 Manipulation de base des ListUne liste de string, par exemple, se construit par :
List<string> liste = new List<string>(); De la même façon que pour les piles et les queues, nous pouvons définir la capacité de notre liste dans le constructeur.
L'ajout- Add(T item) : ajoute l'élément item dans la liste
Exemple :
- AddRange(INumerable collection) : permet d'ajouter à la liste une collection qui implémente l'interface INumerable.
Exemple :
string[] tab = new string[3]; tab[0] = "Supinfo"; tab[1] = "Projet"; tab[2] = "Pérennisation" ; liste.AddRange(tab);
- Insert(int index, T item) : insert l'objet item à l'index.
- InsertRange(int index, INumerable collection) : insert une collection INumerable a l'index.
La suppression
- Clear() : vide la liste (implémentation de ICollection)
- Remove(T item) : supprime l'objet item
- RemoveAt(int index) : supprime l'objet à l'index.
- RemoveRange(int index, int count) : supprime count objet(s) à partir de l'index
- RemoveAll(Predicate match) : permet de supprimer tous les objets qui valide la condition match. Nous verrons l'utilisation de la délégation Predicate un peu plus tard.
Les propriétés
- Capacity : retourne la capacité de la liste.
- Count : retourne ne nombre d'éléments dans la liste.
- Item : on peut récupérer notre objet en get/set à partir son index.
Divers
- AsReadOnly() : permet de renvoyer un wrapper IList en lecture seule de la liste.
- Contains(T item) : renvoi un booléen si l'objet item est présent.
- CopyTo(T[] array) : copie les objets de la liste dans un tableau (array) du même type.
- GetRange(int index, int count) : renvoi une List du même type contenant les count objet(s) de la liste en partant de l'index.
- IndexOf(T item) : retourne l'index de l'objet item
- LastIndexOf(T item) : retourne le dernier index de l'objet item.
- ToArray() : retourne un tableau de la liste du même type.
3.4 La capacitéLa capacité d'une liste par défaut est de zéro sauf si l'on a défini sa capacité dans le constructeur. Dés que l'on ajoute un élément dans une liste où la capacité est saturée, celle-ci double. Nous pouvons supprimer les éléments non utilisés, pour réduire la capacité de la liste afin qu'elle occupe moins de place en mémoire, par la méthode TrimExcess(). Démonstration :
List<int> test_liste = new List<int>(); Console.WriteLine("Capacite initiale: {0}", test_liste.Capacity); for (int a = 0; a < 10; a++) { test_liste.Add(a); Console.WriteLine("Capacite (a={0}): {1}", a, test_liste.Capacity); }
Console.WriteLine("Fin de l'ajout. Nbre d'élément: {0}", test_liste.Count);test_liste.TrimExcess();
Console.WriteLine("Capacite après TrimExcess() : {0}", test_liste.Capacity); // Résultat à l'écran : // Capacite initiale: 0 // Capacite (a=0): 4 // Capacite (a=1): 4 // Capacite (a=2): 4 // Capacite (a=3): 4 // Capacite (a=4): 8 // Capacite (a=5): 8 // Capacite (a=6): 8 // Capacite (a=7): 8 // Capacite (a=8): 16 // Capacite (a=9): 16 // Fin de l'ajout. Nbre d'élément: 10 // Capacite après TrimExcess() : 10
3.5 Utilisation des délégationsIl existe 4 nouvelles délégations fort utiles au sein du namespace System qui nous permette de manipuler les collections :
Ces délégués peuvent être écrit par des méthodes statiques ou méthodes anonymes. Par exemple, pour afficher les éléments d'une liste nous pourrions écrire par méthode anonyme :
List<int> liste_int = new List>();
for (int a = 0; a < 10; a++)
{ liste_int.Add(a); } liste_int.ForEach(delegate(int a) { Console.WriteLine(a); });
Et par méthode statique :
liste_intForEach(afficher);
// ....
static void afficher(int a) { Console.WriteLine(a); });
La méthode ForEach(Action) nous permet donc d'effectuer une "action" pour chaque élément de la liste.
La délégation Converter permet de convertir une liste et s'utilise avec la méthode ConvertAll(Converter) de la liste qui renvoi une liste de type U (T est le type de la liste et U le type après conversion). Exemple d'une conversion simple d'une liste d'entier (nommé ici liste_int) en liste de double par méthode anonyme :
List<double> liste_double = liste_int.ConvertAll<double>(delegate(int a){ return (double)a; });
Les délégation Predicate et Comparaison seront étudiées ci après.
3.6 Utilisation des prédicats (Predicate)Les prédicats sont des délégations qui retournent un booléen. Ils définissent les conditions que doit respecter un élément. Ils servent notamment dans les fonctions de recherches pour définir les conditions de recherche.
Méthodes de la classe List utilisant la délégation Predicate :
- Exist(Predicate match) : retourne un booléen si il existe un élément qui remplit les conditions du prédicat.
- Find(Predicate match) : retourne le 1er élément qui remplit les conditions du prédicat.
- FindAll(Predicate match) : retourne une liste du même type qui contient tous les éléments qui remplissent les conditions du prédicat.
- FindIndex(Predicate match) : retourne l'index du 1er élément qui remplit les conditions du prédicat.
- FindLast(Predicate match) : retourne le dernier élément qui remplit les conditions du prédicat.
- FindLastIndex(Predicate match) : retourne l'index du dernier élément qui remplit les conditions du prédicat.
- RemoveAll(Predicate match) : supprime tous les éléments de la liste qui remplissent les conditions du prédicat.
- TrueForAll(Predicate match) : retourne un booléen si tous les éléments ont remplit les conditions du prédicat.
Exemple : fabriquons une structure Personne contenant le nom, prénom et age d'une "personne" puis créons une liste de type Personne que nous remplirons de quelques personnes mineures (-18ans) et majeures (+18ans). Nous afficherons à l'écran seulement les personnes mineures par l'utilisation d'un FindAll(). Le code pourrait être :
struct Personne { private string _nom; private string _prenom; private int _age; public Personne(string nom, string prenom, int age) { _nom = nom; _prenom = prenom; _age = age; } public string nom { get { return _nom; } set { _nom = value; } } public string prenom { get { return _prenom; } set { _prenom = value; } } public int age { get { return _age; } set { _age = value; } } } static void Main(string[] args) { List<Personne> annuaire = new List<Personne>(10); annuaire.Add(new Personne("WARIN","Sebastien",19)); annuaire.Add(new Personne("DROUVIN","Kevin",18)); annuaire.Add(new Personne("WARIN","Julien",16)); annuaire.Add(new Personne("WARIN","Alexandre",12)); annuaire.Add(new Personne("BALMER","Amaury",20));
List<Personne> personnes_mineures = annuaire.FindAll(delegate(Personne p){ return ((p.age < 18) ? true:false); });
foreach(Personne p in personnes_mineures) { Console.WriteLine("Nom: {0}\tPrenom: {1}\tAge: {2}", p.nom, p.prenom, p.age); } Console.Read() ; } // Résultat à l'écran : // Nom: WARIN Prenom: Julien Age: 16 // Nom: WARIN Prenom: Alexandre Age: 12
Les personnes mineures sont récupérées dans la liste personnes_mineures remplit par la méthode FindAll(). Le
prédicat, écrit par méthode anonyme, renvoie un True quand l’âge de la personne est strictement
inférieure à 18 ans.
3.7 Le trieMéthodes proposées par la classe List :
- Reverse() : inverse l'ordre de la liste.
- Sort(Comparaison) : trie les éléments de la liste a partir de la délégation Comparaison.
Exemple : nous allons reprendre notre annuaire et rajouter un trie sur l'âge de la liste "annuaire" avant de l'afficher. La comparaison ne sera pas écrite en méthode anonyme car elle tient sur plusieurs lignes. Pour rappel une délégation Comparaison prendre 2 paramètres : les deux éléments (e1 et e2) à comparer et renvoit un int. Dans notre cas on retournera -1 si e1 < e2, 0 si e1 = e2 et 1 si e1 > e2 (ordre croissant). Ecrivons donc notre méthode de comparaison par le code :
static int ComparerAge(Personne p1, Personne p2) { if (p1.age < p2.age) return -1; else if (p1.age > p2.age) return 1; else return 0; }
Puis dans notre fonction Main(), rajoutons à la fin :
annuaire.Sort(ComparerAge); foreach (Personne p in annuaire) { Console.WriteLine("Nom: {0}\tPrenom: {1}\tAge: {2}", p.nom, p.prenom, p.age); } // Résultat à l'écran : // Nom: WARIN Prenom: Alexandre Age: 12 // Nom: WARIN Prenom: Julien Age: 16 // Nom: DROUVIN Prenom: Kevin Age: 18 // Nom: WARIN Prenom: Sebastien Age: 19 // Nom: BALMER Prenom: Amaury Age: 20
Enfin, pour avoir les personnes dans l'ordre décroissant, inversons l'ordre de la liste par :
annuaire.Reverse(); // Résultat à l'écran :
// Nom: BALMER Prenom: Amaury Age: 20 // Nom: WARIN Prenom: Sebastien Age: 19 // Nom: DROUVIN Prenom: Kevin Age: 18 // Nom: WARIN Prenom: Julien Age: 16 // Nom: WARIN Prenom: Alexandre Age: 12
Nous aurions pu faire la comparaison en utilisant la classe Comparer, dont on ne parle pas dans cet article, qui fait aussi partie du namescape System.Collection.Generic. Le code aurait pu être :
annuaire.Sort(delegate(Personne p1, Personne p2) { return Comparer.Default.Compare(p1.age, p2.age); });
|