Vous êtes nouveau sur Developpez.com ? Créez votre compte ou connectez-vous afin de pouvoir participer !

Vous devez avoir un compte Developpez.com et être connecté pour pouvoir participer aux discussions.

Vous n'avez pas encore de compte Developpez.com ? Créez-en un en quelques instants, c'est entièrement gratuit !

Si vous disposez déjà d'un compte et qu'il est bien activé, connectez-vous à l'aide du formulaire ci-dessous.

Identifiez-vous
Identifiant
Mot de passe
Mot de passe oublié ?
Créer un compte

L'inscription est gratuite et ne vous prendra que quelques instants !

Je m'inscris !

Retour sur une proposition pour C# 8 : les références nullables
Quels sont les avantages de cette fonctionnalité ?

Le , par François DORIN

0PARTAGES

L'erreur à un milliard de dollars
Connaissez-vous Tony Hoare ? Il y a de grandes chances que non. Pourtant, en tant que développeurs, vous utilisez très certainement le fruit de ses travaux. L'un d'entre eux, qu'il qualifie lui-même comme "l'erreur à 1 milliard de dollars", est le pointeur nul, objet du billet d'aujourd'hui.

Très pratique, le pointeur nul est présent dans de nombreux langages. C++, Java, C# pour ne prendre que les exemples de langages les plus répandus.

Par exemple, en C#, la valeur nulle est la valeur par défaut des types références. Si vous allouez un tableau d'objets, chaque case du tableau est initialisée… à nulle ! Ou encore, lorsqu'on souhaite préciser qu'une variable n'a pas de valeur, on l'initialise là aussi à nulle.

Mais qui n'a jamais eu à souffrir, durant l'exécution de son code, d'un NullPointerException ? Que le développeur à qui cela n'est jamais arrivé lève la main ! Cette erreur est fréquente (sans doute l'erreur la plus répandue !) et indique l'absence de valeur là où on en attend une. Cela oblige donc à tester la valeur de la variable avant de l'utiliser.

Et c'est là que réside le problème de la plupart des langages ayant cette notion. Il n'y a rien pour distinguer une valeur nulle fortuite d'une valeur nulle voulue.

Évolution du langage C#
Le lien avec C#8 ? Il y a actuellement de longues discussions autour d'une fonctionnalité portant le nom de "référence nullable"(nullable reference dans la langue de Shakespeare), qui permettrait justement de préciser si une référence peut être nulle ou non.

Si on passe outre l'aspect rupture du langage, quels seraient les avantages d'une telle approche ? Et bien le principal avantage est de permettre de corriger de nombreux bogues à la compilation, et non plus à l'exécution.

Ainsi, un code comme
Code c# : Sélectionner tout
1
2
3
4
if (hello.Length == 0) 
{}

Générera une erreur si hello est une variable de type String?, mais pas d'erreur si elle est de type String.

Pour un type String?, il faudra vérifier que la référence est non nulle
Code c# : Sélectionner tout
1
2
3
4
if (hello != null && hello.Length == 0) 
{}

En théorie, c'est très intéressant, mais cela soulève encore de nombreux problèmes, dont toutes les questions n'ont pas encore trouvé réponse. Par exemple, que se passe-t-il si une méthode teste le caractère nul d'une variable ? Par exemple :
Code c# : Sélectionner tout
1
2
3
4
5
String? Hello = "world"; 
if (!String.IsNullOrEmpty(hello)) 
{ 
   int taille = hello.Length; // Générera une erreur ! 
}
Pourquoi une erreur ? Nous, en tant que développeurs, nous savons que la méthode String.IsNullOrEmpty teste le caractère nul ou vide d'une chaîne de caractères. Mais le compilateur ne le sait pas lui. Pour résoudre ce problème, deux approches sont envisageables :
  1. La première, rajouter un test de nullité dans la conditionnelle. Pas terrible. En plus d'être redondant, cela alourdit le code ;
  2. La seconde, introduire une nouvelle syntaxe, permettant de dire au compilateur "OK, je sais ce que je fais, ne génère pas d'erreur" (par exemple, int taille = hello.Length!;).


Des zones d'ombre...
De plus, si cette approche permettrait de résoudre certains problèmes, elle n'est pas sans en poser d'autres, qu'il va aussi falloir résoudre avant de pouvoir déployer cette fonctionnalité :
  • une valeur (notamment une propriété) peut très bien devenir nulle entre le moment où elle a été testée et où la valeur est effectivement utilisée ;
  • des méthodes qui retournent des valeurs non nulles pourront malgré tout retourner des valeurs nulles (cas d'une API qui n'aurait pas été mise à jour par exemple).


Une évolution ou une révolution ?
Le plus gros problème de cette approche reste qu'elle implique une évolution même du langage, évolution "cassante" changeant la sémantique de tout code écrit jusqu'à aujourd'hui. On comprend donc les longues discussions qu'il peut y avoir à ce sujet.

Illustrons ceci avec quelques exemples. Aujourd'hui, ce code est tout à fait valide :
Code c# : Sélectionner tout
1
2
String hello = "World"; 
Hello = null;

Demain, ce code ne sera plus valide, et générera une erreur au niveau de la seconde ligne, lors de l'affectation de la valeur null.

Autrement dit, par défaut, les références ne seront plus nullables. Pour retrouver le comportement actuel, il faudra déclarer les variables comme étant nullables :
Code c# : Sélectionner tout
1
2
String? hello = "World"; 
Hello = null; // Opération valide, puisque hello est nullable.

Pour éviter de casser tout le code existant, ce changement ne générera que des avertissements, et non des erreurs. Mais un code propre d'aujourd'hui pourra se retrouver avec des milliers d'avertissements demain !

Affaire à suivre
Les discussions sont loin d'être terminées. On parle déjà de C#8 alors que la prochaine version attendue de C# est la 7.3. Mais ce changement est loin d'être anodin et il est donc nécessaire de l'anticiper largement en amont, car s'il venait à être adopté, cela sera un changement majeur du langage comme jamais il n'en a connu jusqu'à aujourd'hui.

Sources
le projet C# sur github
exemple de discussion sur Reddit (213 commentaires au moment de l'écriture de ce billet, ce qui est énorme !)

Une erreur dans cette actualité ? Signalez-le nous !