Partager via


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

Mise à jour : novembre 2007

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 limitations de l'utilisation de classes de collection non génériques peuvent être démontré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 commode qui peut être utilisée non modifiée 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 être convertis boxed lorsqu'ils sont ajoutés à la liste, et convertis unboxed lorsqu'ils sont récupérés. Les opérations de casting et de conversion (boxing et unboxing) affectent les performances. L'effet des conversions boxing et unboxing peut être très significatif lorsque vous parcourez des 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

Concepts

Guide de programmation C#

Référence

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

System.Collections.Generic

Conversion boxing et unboxing (Guide de programmation C#)

Autres ressources

Collections Best Practices