La gestion des types lors du runtime
Par David Catuhe, posté le 28/07/2003
Profil : Développeur | Niveau : Intermédiaire (200)
1 Introduction
Parmi son lot de simplifications et d'outils pour le développeur, le .NET aura apporté une grande richesse fonctionnelle au niveau de la gestion dynamique des types.
Cette richesse est surtout flagrante pour les développeurs C++ qui n'avaient somme toute que les extensions RTTI (RunTime Type Information) et les ruses des MFC pour obtenir des informations sur le type de leurs objets à l'exécution.
Les développeurs Visual Basic possédaient une intégration plus poussée de ce genre de système sans toutefois avoir la légèreté du .NET.
Nous allons donc passer en revue les possibilités offertes par le .NET pour obtenir le type d'un objet lors du runtime.
2 Les outils de C#
2.1 L'opérateur de cast
Comme son ancêtre, le C#.NET possède l'opérateur de cast qui permet de changer à la volée le type d'un objet vers un type compatible.
Dans le cadre de C#, une exception de type « InvalidCastException » sera levée dans le cas ou la conversion s'avère impossible.
Exemple :
1: int i = 0;
2: float f = 0;
3:
4: f = (float) i;
2.2 L'opérateur is
Cet opérateur binaire permet de tester le type d'un objet lors de l'exécution. Il renvoie un booléen qui sera vrai si l'expression testée n'est pas nulle, est une référence et peut être castée vers le type demandé.
Exemple :
1: int i = 0;
2: object o;
3:
4: o = i;
5:
6: if (o is int)
7: {
8: MessageBox.Show("o est un entier");
9: }
2.3 L'opérateur as
L'opérateur binaire as fonctionne comme un opérateur de cast sauf dans le cadre d'une erreur de cast. Dans ce cas là, il retournera une valeur nulle plutôt que de lever une exception.
Exemple :
1: int i = 0;
2: object o;
3:
4: o = i as string;
5: // o = null ici
2.4 L'opérateur typeof
Cet opérateur permet de retourner un objet de classe System.Type afin d'utiliser les fonctionnalités du framework sur la gestion des types.
Il s'applique sur une classe.
Exemple :
1: System.Type t = typeof(Form);
3 Les outils de Visual Basic.NET
3.1 Le mot clé TypeOf
Ce mot clé permet la comparaison de types et notamment l'appartenance à une hiérarchie de classes.
Exemple :
1: If TypeOf (Me) Is Form Then
2: .
3: End If
3.2 La fonction CType
Cette fonction permet le « cast » à la manière de l'opérateur de cast du C#.NET. Une exception sera levée en cas d'erreur de conversion.
Exemple :
1: Dim i As Integer = 0
2: Dim f As Single
3:
4: f = CType(i, Single)
3.3 La fonction DirectCast
Cette fonction s'utilise de la même manière que le CType mais ne permet le cast que si le type, lors du runtime, de l'objet à convertir est bien celui demandé. Il ne peut y avoir de conversion.
Exemple :
1: Dim i As Integer = 0
2: Dim f As Single
3:
4: f = DirectCast(i, Single) ' ne fonctionne pas
5:
6: Dim o As Object
7: Dim j As Integer
8:
9: o = i
10:
11: j = DirectCast(o, Integer) ' fonctionne
3.4 Les convertisseurs
Visual Basic fournit également des raccourcis pour faire des conversions. En effet, pour les types de base, il existe des méthodes directes de conversion.
Exemple :
1: Dim i As Integer = 0
2: Dim f As Single
3:
4: f = CType(i, Single)
5: f = CSng(i)
4 Les outils du framework
Le framework fournit également des classes pour gérer les informations de type. Le namespace System.Reflection fournit les outils dans ce sens.
Le point d'entrée spécifique est la classe System.Type et il permet de connaître l'ensemble des informations d'une classe : méthodes, propriétés, membres, nom et attributs.
Exemple :
1: Type t = typeof(Form);
2:
3: MethodInfo[] x = t.GetMethods();
4: foreach (MethodInfo xtemp in x)
5: {
6: Console.WriteLine(xtemp.ToString());
7: }
8:
9: Console.WriteLine();
10:
11: MemberInfo[] x2 = t.GetMembers();
12: foreach (MemberInfo xtemp2 in x2)
13: {
14: Console.WriteLine(xtemp2.ToString());
15: }
De la même manière, il est possible par réflexion d'évaluer si une classe hérite d'une autre :
1: Type type = typeof(System.IO.FileStream);
2:
3: if (type.IsSubclassOf(typeof(Form)))
4: {
5: MessageBox.Show("Ok, FileStream est une fille de Form");
6: }
7:
8: if (type.IsSubclassOf(typeof(System.IO.Stream)))
9: {
10: MessageBox.Show("Ok, FileStream est une fille de Stream");
11: }
Toutefois, il est important de noter que la richesse fonctionnelle du namespace System.Reflection va bien au-delà de ces simples tests et peut fournir tous les renseignements que l'on souhaite lors de l'exécution.
5 Remarques
Il faut également souligner que si l'utilisation de la classe System. Type fournit des informations riches, elle possède l'inconvénient d'avoir une certaine lourdeur et une certaine lenteur.
Dans le cadre de tests de type simples, il est donc préférable de faire appel à TypeOf en Visual Basic.NET ou aux opérateurs de cast en C#.NET. Les tests de casts sont générés inline et fournissent des performances maximales pour des consommations de ressources minimes.
6 Conclusion
Finalement, et devant cette pléthore d'outils, il apparaît comme clair que le développement .NET peut s'orienter vers du générique avec du code permettant d'adapter le fonctionnement aux types des objets fournis et ainsi de développer facilement des patterns (factories, etc.).
Passionné de développement et geek dans l’âme. David dirige Bewise qu’il a fondé en 1999 avec ses acolytes Frédéric Colin et Yann Faure. Il est également très impliqué dans le développement du moteur 3D Nova pour la société Vertice qu’il a fondé en 2002 avec son ami Michel Rousseau. Les sujets qui lui tiennent à cœur sont autour des technologies WPF, Silverlight, Windows Phone 7 ou encore DirectX.



