C# a d'ores et déjà acquis une bonne
réputation de langage "d'entreprise", et est notamment crédibilisé
par la fait que le framework .NET soit écrit dans ce langage.
Maintenant que les
spécifications de la version 2 du C# ont été publiées,
nous pouvons nous pencher sur ce qu'apportent lees types génériques
(ou generics) à un langage déjà bien achalandé.
Que sont les Generics ?
Les types génériques existaient déjà du temps du langage
C++ (avec la bibliothèque générique STL
par exemple), sous le nom de templates (modèles). Le concept n'est
donc pas nouveau, mais le fait de l'implanter directement dans la langage plutôt
que de laisser sa réalisation aux bilbiothèques externes, peut en
rendre l'utilisation plus pratique et plus rapide. On peut aussi trouver des formes
de types génériques dans de nombreux autres langages : Ada, Eiffel,
Haskell, Caml...
Les generics existent pour faciliter la
réutilisation du code, idée certes déjà fondamentale
dans la programmation orientée Objet, mais qui est ici poussée un
peu plus loin.
Ils décrivent des classes et méthodes qui peuvent travailler de
manière uniforme avec des valeurs de types différents. L'intérêt
devient évident dès lors que l'on travaille avec un langage fortement
typé : plus besoin de passer par le transtypage...
L'appellation du C++, "modèles",
permet de mieux appréhender leurs fonctionnalités que "types
génériques". En effet, ils permettent de définir des
fonctions et méthodes qui s'adapteront aux types des paramètres
qui leurs sont envoyé, ce qui permet de construire un véritable
template, à la manière de ceux que l'on utilise pour créer
un site Web : l'information, quelle qu'elle soit, s'intègre facilement
au "moule" des generics, permettant de construire de nombreuses
briques et de s'en servir, plutôt que de devoir travailler sur des routines
précises pour des types précis.
Exemple
Les types génériques sont implémentés dans C# de la
même manière que dans C++, afin de ne pas dérouter les programmeurs.
Nous utilisons ici l'exemple classique de la classe Pile,
qui permet de stocker des éléments. Cette classe possède
deux méthodes : Push() permet d'introduire
un élement dans la pile, Pop() de l'en
sortir.
public
class Pile<TypeDeLElement>
{
private TypeDeLElement[] element;
public void Push(TypeDeLElement data)
{
// code gérant l'introduction de l'élément.
}
public TypeDeLElement Pop()
{
// code gérant la sortie de l'élément.
}
}
Pile<char> maPile = new Pile<char>();
maPile.Push("a");
char x = maPile.Pop();
La seule différence avec la déclaration habituelle de la classe
est la présence des caractères < et >, qui permettent de définir
le type que la pile doit avoir comme si c'était un paramètre de
la classe. Lors de l'instanciation de la classe, il faut bien sûr déclarer
le type des données utilisées.
On peut aussi utiliser plusieurs types pour une
classe :
public
class Comparer<Type11, Type1>
{
public Type1 LePlusGrand(Type1 element, Type1 element2)
{
// code gérant la comparaison
}
public Type1 LePlusPetit(Type1 element, Type1 element2)
{
// code gérant la comparaison
}
}
Comparer<int, int> maComp = new Comparer<int, int>;
int monResultat = maComp.LePlusGrand(12, 7);
Nous aurons l'occasion de revenir sur cet apport
important au langage C#.
|