Share via


Avantages des génériques (guide de programmation C#)

Les génériques offrent la solution à une limitation dans les versions antérieures du common language runtime et du langage C# dans lesquels la généralisation s'effectue par casting des types vers et depuis le type de base universel Object. En créant une classe générique, vous pouvez créer une collection qui est de type sécurisé au moment de la compilation.

Les restrictions relatives à l'utilisation de classes de collections non génériques peuvent être illustrées par l'écriture d'un programme court qui utilise la classe de collection ArrayList de la bibliothèque de classes .NET Framework. ArrayList est une classe de collection très pratique qui peut être utilisée sans modification pour stocker tout type référence ou valeur.

// The .NET Framework 1.1 way to create a list:
System.Collections.ArrayList list1 = new System.Collections.ArrayList();
list1.Add(3);
list1.Add(105);

System.Collections.ArrayList list2 = new System.Collections.ArrayList();
list2.Add("It is raining in Redmond.");
list2.Add("It is snowing in the mountains.");

Mais cette commodité a un coût. Tout type référence ou valeur qui est ajouté à un ArrayList est implicitement upcasté en Object. Si les éléments sont des types valeur, ils doivent faire l'objet d'un boxing lorsqu'ils sont ajoutés à la liste, et d'un unboxing lorsqu'ils sont récupérés. Les opérations de casting et de boxing / unboxing affectent les performances. L'effet du boxing et de l'unboxing peut être très significatif lorsque vous itérez au sein de collections très volumineuses.

L'autre limitation réside dans le manque de vérification de type compilation. Puisqu'un ArrayList effectue un cast de tout en Object, il n'existe aucun moyen à la compilation d'empêcher le code client de procéder comme suit :

System.Collections.ArrayList list = new System.Collections.ArrayList();
// Add an integer to the list.
list.Add(3);
// Add a string to the list. This will compile, but may cause an error later.
list.Add("It is raining in Redmond.");

int t = 0;
// This causes an InvalidCastException to be returned.
foreach (int x in list)
{
    t += x;
}

Bien que parfaitement acceptable et parfois intentionnelle si vous créez une collection hétérogène, la combinaison de chaînes et d'entiers (ints) dans une seule ArrayList est plus vraisemblablement une erreur de programmation, et cette erreur ne sera pas détectée avant l'exécution.

Dans les versions 1.0 et 1.1 du langage C#, le seul moyen d'éviter les dangers du code généralisé dans les classes de collections de bibliothèques de classes de base .NET Framework était d'écrire vos propres collections spécifiques à un type. Bien sûr, puisqu'une classe de ce genre n'est pas réutilisable pour plusieurs types de données, vous perdez les avantages de la généralisation, et vous devez réécrire la classe pour chaque type qui sera stocké.

Ce dont ArrayList et d'autres classes semblables ont vraiment besoin est un moyen permettant au code client de spécifier, pour chaque instance, le type de données particulier qu'elles ont l'intention d'utiliser. Cela éviterait la nécessité de devoir effectuer un upcast en T:System.Object et permettrait également au compilateur d'effectuer un contrôle de type. En d'autres termes, ArrayList a besoin d'un paramètre de type. C'est exactement ce que les génériques assurent. Dans la collection List<T> générique, dans l'espace de noms N:System.Collections.Generic, la même opération d'ajout d'éléments à la collection ressemble à ceci :

// The .NET Framework 2.0 way to create a list
List<int> list1 = new List<int>();

// No boxing, no casting:
list1.Add(3);

// Compile-time error:
// list1.Add("It is raining in Redmond.");

Pour le code client, la seule syntaxe ajoutée avec List<T> comparée à ArrayList est l'argument de type dans la déclaration et l'instanciation. En échange de cette complexité de codage légèrement supérieure, vous pouvez créer une liste qui est non seulement plus sûre que ArrayList, mais également considérablement plus rapide, surtout lorsque les éléments de la liste sont des types valeur.

Voir aussi

Référence

Introduction aux génériques (guide de programmation C#)

System.Collections.Generic

Boxing et unboxing (Guide de programmation C#)

Concepts

Guide de programmation C#

Autres ressources

Meilleures pratiques de collections