|
|
Le support de la généricité par
C#2 par Patrick
Smacchia |
Un
problème de C#1 et sa résolution grâce aux types génériques de C#2
Le
problème du typage des éléments d’une collection en C#1
Résolution
élégante du problème à l’aide d’une classe générique de C#2
Vue
d’ensemble de la généricité de C#2
Possibilité
pour un type d’être génériques sur plusieurs types
Types
génériques ouverts et fermés
La
généricité de .NET vs. le mécanisme de templates de C++
Visibilité
d’un type générique
Structures
et interfaces génériques
Possibilité
de créer des alias sur le nom d’un type générique fermé
Possibilité
de contraindre un type paramètre
La
contrainte du constructeur par défaut
La
contrainte type valeur/type référence.
Les
contraintes qui vont manquer dans C#2.
Les
membres d'un type générique
Les
opérateurs et les types génériques
Le
transtypage (casting) et la généricité.
Surcharge
de méthodes virtuelles d’un type générique
Méthodes
génériques et contraintes
Méthodes
virtuelles génériques
Inférence
des types paramètres selon les types des paramètres d’une méthode
générique
Ambiguïté
dans la grammaire de C#2
Les
délégués, les évènements et la généricité
Délégués
génériques et méthodes génériques
Contravariance,
covariance, délégués et généricité
Evènements
et délégués génériques
Réflexion,
attribut, IL et généricité
Evolution
de la classe System.Type
Evolution
des classes System.Reflection.MethodBase et System.Reflection.MethodInfo
Les
attributs et la généricité
La
généricité et le langage IL
La
généricité et le framework .NET
La
sérialisation et la généricité
.NET
Remoting et la généricité
Les
collections et la généricité
Les
domaines ne supportant pas la généricité
Une
bonne connaissance générale de C#1.
Depuis deux ans déjà, DNG s’intéresse de près au support de la généricité par .NET2, basé sur les travaux des chercheurs du laboratoire MS Research Don Syme et Andrew Kennedy. Rien d’étonnant à cela quand on sait que cette caractéristique est considérée par beaucoup comme l’évolution centrale de la version 2 de .NET (Bill Gates a veillé personnellement à ce que le support des génériques soit prêt pour cette version).
J’ai pu m’apercevoir lors de la rédaction du présent article que l’implémentation des génériques n’est pas encore stabilisée à 100%. Les différentes sources d’information (articles, blogs, newsgroups, ouvrage The C# programming language) sont parfois contradictoires et certains résultats obtenus par mes propres tests laissent à penser qu’il reste une poignée de cas à améliorer. En bref, tous ce qui va être dit ici n’est valable que pour la version Beta1 de .NET (build 2.0.40607) et sera rigoureusement vérifié au cas où ce contenu se transformerait en un chapitre un jour...
Dans cet article, nous allons examiner à la loupe la plupart des implications du support de la généricité, au niveau du langage C#2, du CLR et du Framework. Mais avant cela commençons par une petite introduction à la généricité.
Le problème du typage des éléments d’une collection en C#1
Supposons que nous avons à implémenter une classe Stack (pile en français) qui permet d’empiler et de dépiler des éléments. Pour simplifier, nous considérons que la pile ne peut contenir plus qu’un certains nombre d’éléments ce qui nous permet d’utiliser en interne un tableau C#. Voici une implémentation de la classe Stack qui satisfait ces contraintes :
class Stack{
private object[] m_ItemsArray;
private int
m_Index = 0;
public const
int MAX_SIZE = 100;
public Stack(){
m_ItemsArray = new object[MAX_SIZE]; }
public Object Pop(){
if (m_Index ==0 )
throw new InvalidOperationException("Impossible de dépiler un élément d'une pile
vide.");
return m_ItemsArray[--m_Index];
}
public void
Push(Object
item) {
if(m_Index == MAX_SIZE)
throw new StackOverflowException("Impossible d'empiler un élément sur une pile pleine.");
m_ItemsArray[m_Index++] = item;
}
}
Cette implémentation souffre de trois défauts majeurs.
Premièrement, les clients de la classe Stack doivent transtyper
explicitement tout élément obtenu à partir de la pile. Par exemple :
...
Stack stack = new Stack();
stack.Push(1234);
int number = (int)stack.Pop();