Génériques (Classes et Méthodes)
Fait partie de la section Programmation Orientée Objet du Journey C# de Coddy — leçon 42 sur 70.
Les génériques vous permettent d'écrire des classes et des méthodes qui fonctionnent avec n'importe quel type de données tout en maintenant la sécurité de type. Au lieu d'écrire des classes distinctes pour IntList, StringList et DoubleList, vous écrivez une seule classe générique qui les gère toutes.
Une classe générique utilise un paramètre de type, généralement nommé T, entouré de chevrons :
public class Box<T>
{
private T content;
public void Store(T item) => content = item;
public T Retrieve() => content;
}
// Utilisation avec différents types
Box<int> intBox = new Box<int>();
intBox.Store(42);
Box<string> stringBox = new Box<string>();
stringBox.Store("Hello");Lorsque vous créez Box<int>, le compilateur remplace chaque T par int. Cela permet une vérification de type à la compilation - vous ne pouvez pas stocker accidentellement une chaîne de caractères dans une boîte int.
Les méthodes génériques fonctionnent de manière similaire, permettant à une seule méthode d'opérer sur différents types :
public static void Swap<T>(ref T a, ref T b)
{
T temp = a;
a = b;
b = temp;
}
int x = 1, y = 2;
Swap(ref x, ref y); // x=2, y=1Le compilateur déduit le type à partir des arguments, vous n'avez donc pas besoin d'écrire Swap<int> explicitement. Les génériques sont le fondement des collections comme List<T> et Dictionary<TKey, TValue>, permettant un code réutilisable et de type sécurisé.
Défi
FacileConstruisons un système générique Storage<T> capable de contenir et de gérer des éléments de n'importe quel type. Vous allez créer une classe de conteneur réutilisable qui démontre la puissance des génériques : écrivez-la une fois, utilisez-la avec des entiers, des chaînes de caractères ou tout autre type !
Vous organiserez votre code sur deux fichiers :
Storage.cs: Créez une classe génériqueStorage<T>dans l'espace de nomsDataStorage. Votre conteneur de stockage doit :- Avoir un tableau privé de type
Tpour contenir les éléments et une propriétéCountsuivant le nombre d'éléments stockés - Accepter une capacité dans son constructeur pour initialiser le tableau interne
- Avoir une méthode
Add(T item)qui ajoute un élément s'il y a de la place - Avoir une méthode
Get(int index)qui renvoie l'élément à l'index spécifié - Avoir une méthode
GetAll()qui renvoie tous les éléments stockés joints par", "
- Avoir un tableau privé de type
Program.cs: Dans votre fichier principal, démontrez le fonctionnement de votre classe générique avec deux types différents. Créez unStorage<int>et unStorage<string>, ajoutez des éléments à chacun, et montrez que la même classe fonctionne parfaitement avec les deux types.
Vous recevrez quatre entrées :
- Premier entier à stocker
- Deuxième entier à stocker
- Première chaîne à stocker
- Deuxième chaîne à stocker
Créez un stockage d'entiers avec une capacité de 5 et un stockage de chaînes avec une capacité de 5. Ajoutez les deux entiers au stockage d'entiers et les deux chaînes au stockage de chaînes.
Affichez la sortie dans ce format :
Int storage: {GetAll()}
Int count: {Count}
First int: {Get(0)}
String storage: {GetAll()}
String count: {Count}
First string: {Get(0)}Par exemple, si les entrées sont 42, 100, Hello, et World, la sortie devrait être :
Int storage: 42, 100
Int count: 2
First int: 42
String storage: Hello, World
String count: 2
First string: HelloRemarquez comment vous écrivez la classe Storage<T> une seule fois, mais elle fonctionne parfaitement avec int et string - c'est la magie des génériques ! Le compilateur garantit la sécurité des types, vous ne pouvez donc pas ajouter accidentellement une chaîne à votre stockage d'entiers.
Aide-mémoire
Les génériques vous permettent d'écrire des classes et des méthodes qui fonctionnent avec n'importe quel type de données tout en maintenant la sécurité des types.
Une classe générique utilise un paramètre de type (généralement T) entouré de chevrons :
public class Box<T>
{
private T content;
public void Store(T item) => content = item;
public T Retrieve() => content;
}Lors de la création d'une instance, spécifiez le type pour remplacer T :
Box<int> intBox = new Box<int>();
intBox.Store(42);
Box<string> stringBox = new Box<string>();
stringBox.Store("Hello");Les méthodes génériques permettent à une seule méthode d'opérer sur différents types :
public static void Swap<T>(ref T a, ref T b)
{
T temp = a;
a = b;
b = temp;
}
int x = 1, y = 2;
Swap(ref x, ref y); // Le compilateur déduit le type à partir des argumentsLes génériques offrent une vérification de type au moment de la compilation et constituent le fondement des collections telles que List<T> et Dictionary<TKey, TValue>.
Essayez vous-même
using System;
using DataStorage;
class Program
{
public static void Main(string[] args)
{
// Lire les entrées
int num1 = Convert.ToInt32(Console.ReadLine());
int num2 = Convert.ToInt32(Console.ReadLine());
string str1 = Console.ReadLine();
string str2 = Console.ReadLine();
// TODO : Créer un Storage<int> avec une capacité de 5
// TODO : Ajouter les deux entiers au stockage d'entiers
// TODO : Créer un Storage<string> avec une capacité de 5
// TODO : Ajouter les deux chaînes au stockage de chaînes
// TODO : Afficher la sortie dans le format requis
// Stockage d'entiers : {GetAll()}
// Nombre d'entiers : {Count}
// Premier entier : {Get(0)}
// Stockage de chaînes : {GetAll()}
// Nombre de chaînes : {Count}
// Première chaîne : {Get(0)}
}
}
Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Toutes les leçons de Programmation Orientée Objet
1Fondamentaux de la POO
Fichiers externesEspaces de noms et directivesIntro aux classes et objetsLe mot-clé 'this'Méthodes et paramètresChamps vs PropriétésConstructeursInitialiseurs d'objetsRécapitulatif - Calculatrice simple4Héritage
Syntaxe de base de l'héritage (:)Le mot-clé 'base'Mots-clés Virtual & OverrideClasses scelléesLa classe de base 'object'Récapitulatif - Hiérarchie des employés7Fonctionnalités avancées
Surcharge d'opérateursIndexeurs (this[])Redéfinition de ToString()Méthodes d'extensionRécapitulatif - Liste personnalisée10Patrons de conception - Partie 1
Introduction aux patrons de conceptionSingleton Thread-SafePatron FabriquePatron Observateur (Événements)Patron Stratégie2Propriétés et membres statiques
Propriétés auto-implémentéesPropriétés en lecture/écriture seuleChamps et méthodes statiquesClasses statiquesMembres à corps d'expression5Polymorphisme & Interfaces
Polymorphisme : Compilation vs ExécutionInterface vs Classe AbstraiteInterfaces MultiplesInterfaces ExplicitesUpcasting & DowncastingRécapitulatif - Calculateur de Formes8Concepts avancés de la POO
Composition plutôt qu'héritageGénériques (Classes et Méthodes)Délégués et ÉvénementsAttributs et RéflexionIDisposable et l'instruction usingBases de l'Injection de Dépendances11Patrons de conception, Partie 2
Patron CommandePatron AdaptateurPatron DécorateurPatron Méthode TemplatePatron ÉtatPatron Composite3Architecture des classes
Données d'instance vs statiquesMots-clés 'readonly' & 'const'Champs de supportRécapitulatif - Gestionnaire de compte bancaire6Encapsulation
Modificateurs d'accèsPropriétés pour l'encapsulationImplémentation du masquage de donnéesPatterns d'immuabilitéRécapitulatif - Dossiers d'étudiants12Projet : Système de gestion de bibliothèque
Structure du projetModèles Livre et Utilisateur