Generics en C# : guide complet sur l'utilisation et les avantages

Formateur Python en ligne pour débutants

Apprenez Python facilement sans surcharge théorique. Résolvez des tâches pratiques avec vérification automatique et écrivez du code directement dans le navigateur.

Start Course

Generics en C# : pourquoi et comment les utiliser



Les types génériques (Generics) sont l'une des fonctionnalités clés du langage C#, qui permet de créer des classes, des méthodes et des interfaces avec des types paramétrés. Au lieu d'écrire le même code pour chaque type de données, vous l'écrivez une seule fois et spécifiez le type lors de l'utilisation. Cela améliore les performances, la sécurité des types et la réutilisabilité du code. Dans cet article, nous allons voir pourquoi les Generics sont nécessaires, comment les appliquer en pratique et examiner des exemples concrets de .NET.



Pourquoi les Generics sont nécessaires en C#



Avant l'apparition des Generics en C# (version 2.0), les développeurs utilisaient souvent le type object et les collections ArrayList. Cela entraînait deux problèmes :



  • Perte de performance — boxing et unboxing pour les types valeur (int, double, struct).
  • Absence de vérification des types à la compilation — on pouvait accidentellement mettre une chaîne dans une liste de nombres et obtenir une erreur uniquement à l'exécution.


Les Generics résolvent les deux problèmes. Ils permettent de créer des structures de données type-safe sans frais généraux inutiles. Par exemple, List<int> fonctionne avec int sans boxing, et le compilateur ne permettra pas d'y ajouter une chaîne.



Concepts de base des Generics



Classes génériques



Une classe générique est déclarée avec un paramètre de type entre chevrons. Le paramètre de type est un placeholder qui est remplacé par le type réel lors de la création de l'instance.



public class Box<T>{    private T _value;

public Box(T value) { _value = value; }

public T GetValue() => _value;}


Utilisation :



var intBox = new Box<int>(42);var stringBox = new Box<string>("Hello");

Console.WriteLine(intBox.GetValue()); // 42Console.WriteLine(stringBox.GetValue());// Hello


Méthodes génériques



Une méthode peut avoir son propre paramètre de type, même si la classe n'est pas générique :



public class Utils{    public static void Swap<T>(ref T a, ref T b)    {        T temp = a;        a = b;        b = temp;    }}

// Utilisationint x = 1, y = 2;Utils.Swap(ref x, ref y);Console.WriteLine($"{x} {y}"); // 2 1


Interfaces génériques



Les interfaces avec un paramètre de type permettent de créer des abstractions flexibles :



public interface IRepository<T>{    T GetById(int id);    void Add(T entity);}

public class UserRepository : IRepository<User>{ public User GetById(int id) => new User(); public void Add(User user) { }}


Contraintes dans les Generics



Parfois, il est nécessaire d'imposer des restrictions sur les types qui peuvent être substitués. Pour cela, on utilise le mot-clé where.



Principaux types de contraintes



  • where T : class — uniquement les types référence (string, classes).
  • where T : struct — uniquement les types valeur (int, DateTime, struct).
  • where T : new() — le type doit avoir un constructeur public sans paramètres.
  • where T : SomeBaseClass — le type doit être ou hériter de la classe spécifiée.
  • where T : ISomeInterface — le type doit implémenter l'interface.


Exemple avec plusieurs contraintes :



public class Repository<T> where T : class, IEntity, new(){    public T Create()    {        return new T(); // autorisé grâce à new()    }}


Covariance et Contravariance dans les Generics



À partir de C# 4.0, il est possible de gérer la variance des interfaces génériques à l'aide des mots-clés in et out.



  • Covariance (out) — permet d'util

Blogs

Book Recommendations