English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية

Générique C#

Les génériques sont une forme générale, pas une forme spécifique. En C#, les génériques ne sont pas spécifiques à un type de données spécifique.

C# vous permet d'utiliser des paramètres de type sans spécifier de type de données spécifique pour définir des classes génériques, des interfaces, des classes abstraites, des champs, des méthodes, des méthodes statiques, des propriétés, des événements, des délégués et des opérateurs. Les paramètres de type sont des substituts de types spécifiques spécifiés lors de la création d'une instance de type générique.

La déclaration générique est effectuée en spécifiant un paramètre de type après le nom du type, par exemple TypeName<T>, où T est le paramètre de type.

Classe générique

Les classes génériques sont définies en utilisant des paramètres de type dans les crochets après le nom de la classe. Voici une classe générique définie.

class DataStore<T>
{
    public T Data { get; set; }
}

Dans l'exemple ci-dessus, DataStore est une classe générique. T est appelé paramètre de type et peut être utilisé pour les champs, les propriétés, les paramètres de méthode, le type de retour et les délégués de la classe DataStore. Par exemple, Data est une propriété générique car nous avons utilisé le paramètre de type T comme son type, plutôt qu'un type de données spécifique.

Attention : généralement, T peut être utilisé pour un seul type de paramètre. Si il y a plusieurs types de paramètres, n'utilisez pas T comme type de paramètre et attribuez n'importe quel nom aux types de paramètres. Il est recommandé d'utiliser des noms de types de paramètres plus lisibles, tels que TSession, TKey, TValue, etc.

Vous pouvez également définir plusieurs types de paramètres et les séparer par des virgules.

class KeyValuePair<TKey, TValue>
{
    public TKey Key { get; set; }
    public TValue Value { get; set; }
}

Instanciation de la classe générique

Vous pouvez créer des instances de classes génériques en spécifiant le type réel entre crochets. Voici comment créer une instance de la classe générique DataStore.

DataStore<string> store = new DataStore<string>();

Ci-dessus, nous avons spécifié le type string entre crochets lors de la création de l'instance. Par conséquent, T sera remplacé par le type T utilisé partout dans la classe au moment de la compilation. Par conséquent, le type de l'attribut Data est string.

La figure suivante explique comment fonctionne le générique.

Vous pouvez assigner une valeur de chaîne à l'attribut Data. Tenter d'assigner une valeur autre qu'une chaîne entraînera une erreur à la compilation.

DataStore<string> store = new DataStore<string>();
store.Data = "Hello World!";//obj.Data = 123; //Erreur à la compilation

Vous pouvez spécifier différents types de données pour différents objets, comme indiqué ci-dessous.

DataStore<string> strStore = new DataStore<string>();
strStore.Data = "Hello World!";
//strStore.Data = 123; // Erreur à la compilation
DataStore<int> intStore = new DataStore<int>();
intStore.Data = 100;
//intStore.Data = "Hello World!"; // Erreur à la compilation
KeyValuePair<int, string> kvp1 = new KeyValuePair<int, string>();
kvp1.Key = 100;
kvp1.Value = "Hundred";
KeyValuePair<string, string> kvp2 = new KeyValuePair<string, string>();
kvp2.Key = "IT";
kvp2.Value = "Information Technology";

Caractéristiques des classes génériques

  • Les classes génériques augmentent la réutilisabilité. Plus les types sont nombreux, plus la réutilisabilité est élevée. Cependant, une excessive généralisation rend le code difficile à comprendre et à maintenir.

  • Une classe générique peut être la base d'autres classes génériques ou non génériques ou d'abstract classes.

  • Une classe générique peut hériter d'autres interfaces génériques ou non génériques, de classes ou d'abstract classes.

Champ générique

Une classe générique peut contenir des champs génériques. Cependant, ils ne peuvent pas être initialisés.

class DataStore<T>
{
    public T data;
}

Déclaration d'un tableau générique.

class DataStore<T>
{
    public T[] data = new T[10];
}

泛型方法

使用类型参数声明其返回类型或参数的方法称为泛型方法。

class DataStore<T>
{
    private T[] _data = new T[10];
    
    public void AddOrUpdate(int index, T item)
    {
        if(index >= 0 && index < 10)
            _data[index] = item;
    }
    public T GetData(int index)
    {
        if(index >= 0 && index < 10)
            return _data[index];
        else 
            return default(T);
    }
}

上面的 AddorUpdate() 和 GetData() 方法是泛型方法。item参数的实际数据类型将在实例化 DataStore<T> 类时指定,如下所示。

DataStore<string> cities = new DataStore<string>();
cities.AddOrUpdate(0, "Mumbai");
cities.AddOrUpdate(1, "Chicago");
cities.AddOrUpdate(2, "London");
DataStore<int> empIds = new DataStore<int>();
empIds.AddOrUpdate(0, 50);
empIds.AddOrUpdate(1, 65);
empIds.AddOrUpdate(2, 89);

泛型参数类型可以与带有或不带有非泛型参数和返回类型的多个参数一起使用。以下是有效的泛型方法重载。

public void AddOrUpdate(int index, T data) { }
public void AddOrUpdate(T data1, T data2) { }
public void AddOrUpdate<U>(T data1, U data2) { }
public void AddOrUpdate(T data) { }

通过在尖括号中使用方法名称指定类型参数,非泛型类可以包含泛型方法,如下所示。

class Printer
{
    public void Print<T>(T data)
    {
        Console.WriteLine(data);
    }
}
Printer printer = new Printer();
printer.Print<int>(100);
printer.Print(200); // Inférence de valeur spécifiée
printer.Print<string>("Hello");
printer.Print("World!"); // Inférence de valeur spécifiée

Avantages des génériques

  1. Les génériques améliorent la réutilisabilité du code. Vous n'avez pas besoin d'écrire de code pour gérer différents types de données.

  2. Les génériques sont sécurisés en termes de type. Si vous essayez d'utiliser un type de données différent de celui spécifié dans la définition, une erreur de compilation se produira.

  3. Les génériques ont un avantage en termes de performance car ils éliminent la possibility d'emballage et de dépaquetage.