Une remarque pertinente ?
Une critique impertinente ?
Un lynchage en règle ?
Une invitation sous les tropiques ?

Ecrivez-moi !

Conçu et enseigné tel qu'en lui même, avec pertes, fracas et humour de qualité supérieure            
 par Christophe Darmangeat dans le M2 PISE du Master MECI (Université Paris 7)            


 

 

 

Référence du langage

Les conversions de types

Comme dans tous les langages informatiques, les informations en C# sont stockées dans des blocs de mémoire, en réservant un certain nombre d'octets et en utilisant une certaine méhode de codage. Ce que l'on résume en disant que les variables ont un type. Oui mais voilà, il arrive très souvent qu'au cours d'une application, on ait besoin de reverser les informations stockées dans des variables d'un certain type vers des variables d'un autre type, ce qu'on appelle la conversion.

Les langages ont tous une approche différente du problème des types et des conversions.

  • Certains sont extrêmement permissifs (d'aucuns diront laxistes) : sans parler de les déclarer, ils n'obligent même pas le programmeur à donner des types aux variables : leur type, en caoutchouc, est automatiquement changé « à la volée », en cours d'exécution, si on entre dans la variable un autre genre de données. Un représentant de ce genre de langage est le Python.
  • Certains pratiquent une permissivité relative : ils obligent à typer les variables et n'apprécient guère un changement de type impromptu, mais sont assez conciliants sur les reversements d'information d'un type vers un autre. C'est par exemple le cas de VB.Net.
  • Enfin, certains langages sont franchement psychorigides. Impitoyables sur le typage des informations, ils ne tolèrent aucun écart et hurlent dès que l'on tente de copier une information d'un certain type vers un contenant d'un autre type, exigeant que le programmeur écrive explicitement les instructions de conversion. Devinez quoi ? C# est de ceux-là.

Pour prendre un parallèle avec notre belle planète, en Python, on est dans un monde sans frontières : chacun individu est libre de voyager et de s'établir où il veut sans que personne ne lui demande rien. En VB.Net, il y a des frontières et les individus possèdent des nationalités, mais les douaniers ne sont pas spécialement pénibles, et ne contrôlent les passeports qu'en cas de problème avéré. Avec C#, on est dans notre monde réel, celui ou le franchissement de (certaines) frontières donnera lieu à mille tracasseries, inspirant de belles oeuvres telles que Welcome, Continents à la dérive ou Le vaisseau des morts...

Ce qui est une calamité inhumaine dans le monde réel possède certains avantages en programmation : si, en C#, le compilateur va surveiller nos variables de très près, ce sera pour nous autres programmeurs la garantie que nos applications manipulent les variables de manière rationnelles, et que nous ne sommes pas entrain de leur faire faire n'importe quoi.

1. Entre types compatibles

On sait qu'en informatique, certains types ne sont que des versions plus larges d'autres types. Ainsi, parmi les entiers, le long est une version plus puissante du int, qui est lui-même une version plus puissante du short. Parmi les nombres à virgule, le double est une version plus puissante du float.

1.1 Depuis la petite boîte vers la grande

C'est évidemment le cas le plus facile : « qui peut le plus, peut le moins », comme le sait la sagesse populaire. Une valeur qui loge dans une « petite » variable logera a fortiori dans une plus grande. Dans ce cas – et c'est bien le seul – les douaniers nous laissent passer sans nous poser de questions :

int petit = 12 542;
long grand;
grand = petit

Et l'affaire est dans le sac.

1.2 Depuis la grande boîte vers la petite : le casting

Là où les choses se compliquent un peu, c'est lorsqu'on veut passer le contenu depuis un type plus large vers un type plus étroit. En effet, rien ne dit que ça va rentrer... Aussi, conformément à sa philosophie générale, C# nous oblige à demander expressément une autorisation à la maréchaussée, en baptisant au passage cette opération du terme de « casting » (ah là là, ces informaticiens, toujours en train de se la péter avec du jargon franglais...)

Voici donc la syntaxe pour « caster » (et pourquoi j'aurais pas le droit, moi aussi, de me la raconter ?) un long vers un int :

long grand = 12 542;
int petit;
petit = (int)grand

Une telle opération se fera à nos risques et périls : on peut demander à une machine de verser 2 litres d'eau dans une bouteille de 1 litre... mais alors, fatalement ça déborde. Recopier un long dans un int ne pose donc aucun problème... à condition que la valeur contenue dans le long n'excède pas 2 147 483 647.

Que se passera-t-il dans le cas contraire ?

Tout dépend des types concernés. Il pourra arriver que l'exécution s'interrompe dans un long hurlement de douleur, et dans un message ne laissant aucun doute sur l'origine du mal. Il pourra aussi arriver, de manière plus vicieuse, qu'aucune erreur ne soit signalée, mais que la machine tronque allègrement la valeur concernée, inscrivant ainsi un résultat totalement fantaisiste dans la variable de destination...

2. Entre types de nature différentes

Ce que l'on a dit jusqu'ici concernanit les transferts au sein de types globalement similaires : des entiers, des décimaux (et, ajouterai-je : des contrôles). Mais il se peut qu'ait à convertir des types qui n'ont a priori rien à voir les uns avec les autres. Typiquement, le cas ultra-classique est celui de la chaîne de caractères qui contient un nombre, entier ou décimal, sous forme d'une série de caractère, et qu'on veut récupérer en tant que nombre. Ou, inversement, de la variable numérique qu'on veut transformer en chaîne pour l'afficher quelque part sur la Form.

C# offre deux catégories de solutions en pareil cas :

2.1 La technique sans filet

Il existe une série de méthodes de la classe Convert, qui permettent de convertir tout type en un autre. Typiquement, Convert.ToInt32 convertit une chaîne en entier ; Convert.ToString convertit tout nombre en chaîne, etc. Le truc, en particulier si l'on convertit une chaîne en nombre, c'est qu'on n'est pas forcémen certain que la chaîne correspond bien à un nombre valide. Si ce le cas, pas de problème. Mais si la chaîne contient par exemple « James007 », sa conversion en entier provoquera illico une exception, c'est-à-dire un crash de l'application.

2.2 La technique avec filet

Aussi pourra-t-on, au moins dans certaines circonstances, préférer la méthode TryParse, disponible pour tous les types de données. Cette méthode renvoie un booléen qui indique si la conversion s'est bien déroulée ou non, ainsi qu'un paramètre en sortie – la variable contenant éventuellement la valeur une fois convertie. Une conversion de la chaîne matricule vers un entier numMatricule pourra aini s'écrire :

if (int.TryParse(chaineAge, out numMatricule))
{
conversion effectuée, stockée dans numMatricule
}
else
{
conversion ratée, mais application pas plantée !
}