Mettre à jour un code base avec des types référence pouvant accepter la valeur Null pour améliorer les avertissements de diagnostics Null

Les types de référence nullables vous permettent de déclarer si les variables d’un type référence doivent ou ne doivent pas être affectées à une valeur null. L’analyse statique et les avertissements du compilateur lorsque votre code peut faire l’objet d’une déréférencement null constituent l’avantage le plus important de cette fonctionnalité. Une fois activé, le compilateur génère des avertissements qui vous aident à éviter de lever System.NullReferenceException une fois votre code exécuté.

Si votre codebase est relativement petit, vous pouvez activer la fonctionnalité dans votre projet, traiter les avertissements et profiter des avantages des diagnostics améliorés. Les bases de code plus volumineuses peuvent nécessiter une approche plus structurée pour traiter les avertissements au fil du temps, ce qui active la fonctionnalité pour certains d’entre eux lorsque vous adressez des avertissements dans différents types ou fichiers. Cet article décrit différentes stratégies pour mettre à jour une base de code et les compromis associés à ces stratégies. Avant de commencer votre migration, lisez la vue d’ensemble conceptuelle des types de références nullables. Celle-ci couvre l’analyse statique du compilateur, les valeurs d’état nullmaybe-null et not-null et les annotations nullables. Une fois que vous connaîtrez ces concepts et termes, vous serez prêt à migrer votre code.

Planifier votre migration

Quelle que soit la façon dont vous mettez à jour votre codebase, l’objectif est que les avertissements nullables et les annotations nullables soient activés dans votre projet. Une fois que vous atteignez cet objectif, vous aurez le paramètre <nullable>Enable</nullable> dans votre projet. Vous n’aurez pas besoin des directives de préprocesseur pour ajuster les paramètres ailleurs.

Le premier choix consiste à définir la valeur par défaut du projet. Les choix sont les suivants :

  1. Désactivation nullable comme valeur par défaut : la désactivation est la valeur par défaut si vous n’ajoutez pas d’élément Nullable à votre fichier projet. Utilisez cette valeur par défaut lorsque vous n’ajoutez pas activement de nouveaux fichiers à la base de code. L’activité principale consiste à mettre à jour la bibliothèque pour utiliser des types de référence nullables. L’utilisation de cette valeur par défaut signifie que vous ajoutez une directive de préprocesseur nullable à chaque fichier lorsque vous mettez à jour son code.
  2. Activation nullable comme valeur par défaut : définissez cette valeur par défaut lorsque vous développez activement de nouvelles fonctionnalités. Vous souhaitez que tout nouveau code tire parti des types de référence nullables et de l’analyse statique nullable. L’utilisation de cette valeur par défaut signifie que vous devez ajouter un #nullable disable au début de chaque fichier. Vous supprimerez ces directives de préprocesseur lorsque vous traiterez les avertissements dans chaque fichier.
  3. Avertissements nullables comme valeur par défaut : choisissez cette valeur par défaut pour une migration en deux phases. Dans la première phase, adressez les avertissements. Dans la deuxième phase, activez les annotations pour déclarer l’état null attendu d’une variable. L’utilisation de cette valeur par défaut signifie que vous devez ajouter un #nullable disable au début de chaque fichier.
  4. Annotations nullables comme valeur par défaut. Annotez le code avant de traiter les avertissements.

L’activation nullable comme valeur par défaut crée un travail plus frontal pour ajouter les directives de préprocesseur à chaque fichier. L’avantage est que chaque nouveau fichier de code ajouté au projet sera nullable. Tout nouveau travail prend en compte la valeur Null ; seul le code existant doit être mis à jour. La désactivation de la valeur nullable comme valeur par défaut fonctionne mieux si la bibliothèque est stable et que le principal objectif du développement est d’adopter des types de référence nullables. Vous activez les types de référence nullables en annotant les API. Une fois que vous avez terminé, vous activez les types de référence nullables pour l’ensemble du projet. Lorsque vous créez un nouveau fichier, vous devez ajouter les directives de préprocesseur et le rendre nullable. Si des développeurs de votre équipe l’oublient, ce nouveau code se trouve désormais dans le backlog de travail pour rendre tout code nullable.

La stratégie que vous choisissez dépend de la quantité de développement actif qui se déroule dans votre projet. Plus votre projet est mature et stable, plus la deuxième stratégie est efficace. Plus les fonctionnalités sont développées, plus la première stratégie est efficace.

Important

Le contexte global pouvant accepter la valeur Null ne s’applique pas aux fichiers de code générés. Dans l’une ou l’autre stratégie, le contexte pouvant accepter la valeur Null est désactivé pour tout fichier source marqué comme généré. Cela signifie que des API dans les fichiers générés ne sont pas annotées. Il existe quatre façons de marquer un fichier comme généré :

  1. Dans .editorconfig, spécifiez generated_code = true dans une section qui s’applique à ce fichier.
  2. Placez <auto-generated/> ou <auto-generated> dans un commentaire en haut du fichier. Il peut se trouver sur n’importe quelle ligne de ce commentaire, mais le bloc de commentaires doit être le premier élément du fichier.
  3. Le nom du fichier doit commencer par TemporaryGeneratedFile_.
  4. Le nom du fichier doit se terminer par .designer.cs, .generated.cs, .g.cs ou .g.i.cs.

Les générateurs peuvent s’inscrire à l’aide de la directive de préprocesseur #nullable.

Comprendre les contextes et les avertissements

L’activation d’avertissements et d’annotations contrôle la façon dont le compilateur traite les types de référence et la nullabilité. Chaque type a l’une des trois capacités Null :

  • oblivious : tous les types de références sont inconscients à la valeur Null lorsque le contexte d’annotation est désactivé.
  • nonnullable : type de référence non annoté, C n’est pas nullable lorsque le contexte d’annotation est activé.
  • nullable : type de référence annoté, C? est nullable, mais un avertissement peut être émis lorsque le contexte d’annotation est désactivé. Les variables déclarées avec var sont nullables lorsque le contexte d’annotation est activé.

Le compilateur génère des avertissements en fonction de cette nullabilité :

  • Les types nonnullable provoquent des avertissements si une valeur potentielle null est affectée à ces derniers.
  • Les types nullable provoquent des avertissements s’ils se déréférencent en maybe-null.
  • Les types oblivious provoquent des avertissements s’ils se déréférencent en maybe-null et que le contexte d’avertissement est activé.

Chaque variable a un état nullable par défaut qui dépend de sa nullabilité :

  • Les variables nullables ont comme état null par défaut maybe-null.
  • Les variables non-nullables ont comme état null par défaut not-null.
  • Les variables inconscientes nullables ont comme état null par défaut not-null.

Avant d’activer les types de référence nullables, toutes les déclarations de votre codebase sont oblivious. Cela est important, car cela signifie que tous les types de référence ont un état null par défaut non null.

Avertissements d’adresse

Si votre projet utilise Entity Framework Core, vous devez lire leurs instructions sur l’utilisation de typesde référence nullable.

Lorsque vous démarrez votre migration, vous devez commencer par activer uniquement les avertissements. Toutes les déclarations restent oublivious, mais vous verrez des avertissements lorsque vous déréférencerez une valeur après que son état null change en maybe-null. Lorsque vous traitez ces avertissements, vous vérifierez la valeur Null dans d’autres emplacements, et votre codebase deviendra plus résilient. Pour découvrir des techniques spécifiques pour différentes situations, consultez l’article sur les techniques de résolution des avertissements nullables.

Vous pouvez traiter les avertissements et activer les annotations dans chaque fichier ou classe avant de continuer avec d’autres codes. Toutefois, il est souvent plus efficace de traiter les avertissements générés pendant que le contexte est avertissements avant d’activer les annotations de type. De cette façon, tous les types sont oblivious jusqu’à ce que vous ayez traité le premier ensemble d’avertissements.

Activer les annotations de type

Après avoir adressé le premier ensemble d’avertissements, vous pouvez activer le contexte d’annotation. Cela modifie les types de référence d’oblivious à nonnullable. Toutes les variables déclarées avec var sont nullables. Cette modification introduit souvent de nouveaux avertissements. La première étape de l’adressage des avertissements du compilateur consiste à utiliser des annotations ? sur les types de paramètres et de retour pour indiquer quand des arguments ou des valeurs de retour peuvent être null. En effectuant cette tâche, votre objectif n’est pas simplement de corriger les avertissements. L’objectif le plus important est de faire comprendre au compilateur votre intention pour les valeurs null potentielles.

Les attributs étendent les annotations de type

Plusieurs attributs ont été ajoutés pour exprimer des informations supplémentaires sur l’état null des variables. Les règles de vos API sont probablement plus complexes que non-null ou maybe-null pour tous les paramètres et valeurs de retour. La plupart de vos API ont des règles plus complexes pour les variables pouvant ou ne pouvant pas être null. Dans ces cas-là, vous utiliserez des attributs pour exprimer ces règles. Les attributs qui décrivent la sémantique de votre API se trouvent dans l’article sur les attributs affectant l’analyse nullable.

Étapes suivantes

Une fois que vous avez résolu tous les avertissements après l’activation des annotations, vous pouvez définir le contexte par défaut pour que votre projet soit activé. Si vous avez ajouté des pragmas dans votre code pour l’annotation nullable ou le contexte d’avertissement, vous pouvez les supprimer. Au fil du temps, vous pouvez voir de nouveaux avertissements. Vous pouvez écrire du code qui introduit des avertissements. Une dépendance de bibliothèque peut être mise à jour pour les types de référence nullables. Ces mises à jour modifient les types de cette bibliothèque d’oblivious à nonnullable ou nullable.

Vous pouvez également explorer ces concepts dans notre module Learn sur la sécurité des valeurs Null en C#.