1. Introduction
Imagine : t'as une collection... et tu veux choper vite fait le troisième, le septième ou, genre, le zéroième élément. Ou les échanger. Avec un tableau, c'est easy — via l'index (array[3]). Mais pour les collections ? Bah ouais, toutes les collections sont pas indexables pareil !
C'est là que débarque l'interface IList<T> — un contrat universel qui exige de la collection qu'elle gère les éléments par index. En bref : si ta collection implémente IList<T>, tu peux y accéder par index (comme un tableau) et les modifier à la volée.
Petite analogie :
Pense à une fiche de bibliothèque : chaque livre a son numéro sur l'étagère, et tu peux toujours aller prendre le "troisième dans l'ordre". Voilà comment se comporte une collection qui supporte IList<T>.
2. Structure générale et méthodes de IList<T>
L'interface IList<T>, c'est la star de plein de collections. Elle étend ICollection<T> (qui elle-même étend IEnumerable<T>, ce qui permet de parcourir la collection avec des boucles), et elle ajoute le plus important : la gestion de l'index.
Schéma d'héritage des interfaces :
IEnumerable<T>
▲
│
ICollection<T>
▲
│
IList<T>
Membres principaux de l'interface IList<T>
| Membre | But |
|---|---|
|
Obtenir ou définir un élément par index |
|
Trouver l'index de la première occurrence d'un élément |
|
Insérer un élément à une position donnée |
|
Supprimer un élément par index |
Tous les autres membres, genre Add, Remove, Clear, Contains, viennent de l'interface ICollection<T>.
Le truc clé : l'indexeur
Le gros "plus" de IList<T>, c'est l'indexeur. C'est du sucre syntaxique qui te permet d'écrire :
var myList = new List<int> { 10, 20, 30 };
int secondValue = myList[1]; // On chope 20
myList[2] = 42; // On change le troisième élément
3. Quelles collections implémentent IList<T>
Dans la lib standard .NET, plein de structures connues supportent l'interface IList<T>. Mate les plus populaires :
| Collection | Indexation | Description |
|---|---|---|
|
Oui | Tableau dynamique |
|
Oui | Les tableaux classiques sont indexables |
|
Oui | Utilisé pour le data binding |
|
Oui | Liste avec notifications |
|
Oui | Classe de base pour les collections |
Attention :
LinkedList<T> et
HashSet<T>
NE supportent
IList<T>, parce qu'ils n'ont pas d'indexation rapide (ouais,
LinkedList<T> n'a pas de
list[5] !).
4. Exemples d'utilisation de IList<T>
Obtenir et définir par index
using System;
using System.Collections.Generic;
class Program
{
static void Main()
{
IList<string> fruits = new List<string> { "Pomme", "Banane", "Poire" };
// Obtenir le deuxième élément
string fruit = fruits[1];
Console.WriteLine(fruit); // Banane
// Remplacer le troisième élément
fruits[2] = "Orange";
Console.WriteLine(fruits[2]); // Orange
}
}
Insertion et suppression par index
fruits.Insert(1, "Kiwi"); // On insère "Kiwi" en deuxième position
// Liste maintenant : "Pomme", "Kiwi", "Banane", "Orange"
fruits.RemoveAt(0); // On supprime le premier élément ("Pomme")
// Liste maintenant : "Kiwi", "Banane", "Orange"
Recherche de l'index d'un élément
int index = fruits.IndexOf("Orange"); // Retourne l'index (2) ou -1 si pas trouvé
if (index != -1)
Console.WriteLine("Orange est à la position : " + index);
else
Console.WriteLine("Orange pas trouvé");
5. Particularités d'implémentation et erreurs classiques
Quand tu bosses avec IList<T>, tu peux vite tomber dans quelques "pièges", surtout si t'oublies que l'indexation commence à zéro, et que la longueur de la collection, c'est le nombre réel d'éléments.
Par exemple, essayer d'accéder à un élément qui existe pas :
Console.WriteLine(fruits[100]); // IndexOutOfRangeException !
Les index en C#, c'est comme les poules pondeuses : ça commence à zéro, pas à un. Si t'as 4 éléments, le dernier index dispo c'est 3.
Faut aussi se rappeler que toutes les implémentations de IList<T> sont pas aussi rapides. Genre, pour un tableau ou List<T>, l'accès par index est instantané (O(1)), mais si tu fais ta propre collection basée sur une liste chaînée et que tu lui colles IList<T>, ça peut devenir lent. Même si la lib standard fait pas ça.
Encore un truc : si tu utilises un tableau comme IList<T>, tu peux changer les éléments, mais pas la taille du tableau. Les méthodes Add, Remove, Insert etc. sur un tableau vont balancer une NotSupportedException.
int[] myArray = { 1, 2, 3 };
IList<int> listView = myArray; // Upcast
listView[0] = 42; // Ça marche !
listView.Add(99); // Va balancer NotSupportedException
6. Application pratique et pourquoi c'est utile
Dans les vrais projets, quasi une collection sur deux, c'est un truc qui implémente IList<T>, parce que c'est trop pratique d'accéder vite fait aux éléments par numéro, de les modifier, d'en insérer ou d'en supprimer à une position précise. Par exemple :
- Des propriétés d'interface dans une ViewModel WPF ou WinForms, où tu bindes des listes d'UI éléments.
- L'implémentation d'algo de tri, de recherche, de permutation, où t'as besoin d'accès par index.
- Des modules d'import/export de données qui bossent avec des listes dynamiques d'objets.
En entretien, la question sur la différence entre IEnumerable<T>, ICollection<T> et IList<T>, c'est du classique. Si tu sais à quoi sert chaque niveau, tu peux expliquer tranquille à l'intervieweur pourquoi HashSet<T> n'implémente pas IList<T> (parce que l'unicité est plus importante que l'ordre et les index !).
GO TO FULL VERSION