Remarque
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de vous connecter ou de modifier des répertoires.
L’accès à cette page nécessite une autorisation. Vous pouvez essayer de modifier des répertoires.
Conseil / Astuce
Nouveautés des types de référence nullables ? Lisez d’abord les types de référence Nullables pour comprendre les annotations et l’analyse de l’état Null. Cet article suppose que vous voyez des avertissements dans un projet dans lequel la fonctionnalité est activée.
Vous recherchez un code d’erreur de compilateur spécifique ? L’article de référence Résoudre les avertissements de types nullable répertorie chaque avertissement CS86xx avec la technique correspondante.
Lorsque vous activez des types de référence nullables, le compilateur émet des avertissements partout où le comportement de votre code ne correspond pas à ses annotations. La plupart des avertissements se trouvent dans un petit ensemble de modèles. Une fois que vous avez reconnu le modèle, le correctif est généralement l’une des cinq techniques suivantes :
- Ajoutez une vérification de valeur nulle.
- Ajoutez ou supprimez une annotation
?ou!. - Ajoutez un attribut qui décrit le contrat Null.
- Initialisez correctement les variables.
- Vérifiez le paramètre du projet.
Cet article décrit chaque technique avec un exemple représentatif. L’objectif n’est pas de faire silence les avertissements. Il s’agit de rendre explicite l’intention de gestion null du code afin que le compilateur atteigne les mêmes conclusions que celles que vous faites.
État de nullité : ce que le compilateur suit
Avant d’examiner les techniques, il permet de savoir comment le compilateur suit les violations potentielles de l’état null. Au fur et à mesure qu’il lit votre code, le compilateur effectue le suivi de l’état null de chaque expression : son analyse sur la question de savoir si l’expression peut se trouver null à ce stade dans le code. L’état null est l’une des deux valeurs suivantes :
-
not-null : le compilateur peut prouver que l’expression n’est pas
nullici. Vous pouvez l’utiliser en toute sécurité sans vérification. -
peut-être null - le compilateur ne peut pas exclure
null. L’utilisation de l’expression sans la vérifier produit un avertissement.
L’état null d’une variable change lorsque le compilateur suit votre code. Une méthode qui peut retourner null produit un résultat peut-être null . Une vérification if (x is not null) restreint x à non nul à l’intérieur du bloc if. Les avertissements que vous voyez sont le compilateur qui vous indique qu’une expression est dans un état peut-être null et que vous êtes sur le point de l’utiliser comme s’il n’était pas null. Chaque technique du reste de cet article est un moyen différent de donner au compilateur les informations dont il a besoin pour s’assurer qu’une expression n’est pas null avant de l’utiliser.
Ajouter une vérification null
L’avertissement le plus courant est le déréférencement possible de null. Le compilateur a suivi l’état null d’une variable sur peut-être null et a vu la variable utilisée sans vérification :
public static int LengthOfMessageUnsafe(string? message)
{
// Warning CS8602: dereference of a possibly null reference.
return message.Length;
}
Le correctif est généralement une clause de garde. Une clause guard est une vérification en haut d’une méthode ou d’un bloc qui retourne ou lève lorsqu’une entrée n’est pas valide. Seul le chemin d’accès sécurisé se poursuit. Une fois la vérification effectuée, le compilateur met à jour l’état de nullité de la variable à non null dans le chemin sûr :
public static int DereferenceFixed(string? message)
{
if (message is null)
{
return 0;
}
// No warning: the compiler knows message is not-null on this path.
return message.Length;
}
Correspondance de modèle (expressions telles que is null ou is { } qui testent la forme d’une valeur), ??et ??= incluent des vérifications null :
public static int NullOperatorsFix(string? message)
{
// ?. evaluates to null if message is null; ?? supplies the fallback value.
int length = message?.Length ?? 0;
// Pattern matching narrows the type on the matching branch.
if (message is { Length: > 0 })
{
length = message.Length;
}
return length;
}
Le modèle { Length: > 0 } de propriété correspond uniquement lorsqu’il message n’est pas null et que sa Length propriété est supérieure à zéro, de sorte que le compilateur traite message comme non null à l’intérieur du if bloc. Un test plus simple is not null permet le même affinement de l’état de valeur null sans inspecter aucune propriété.
Pour une présentation détaillée des opérateurs, consultez opérateurs null.
Ajuster les annotations
Le compilateur vous avertit également lorsque votre code affecte une expression peut-être null à une variable non nullable. Cet avertissement signifie l’une des deux choses suivantes :
- La variable doit autoriser les valeurs Null. Dans ce cas, ajoutez un
?au type. - L’expression ne produit jamais de valeur Null. Annotez l’API qui l’a produite.
public static void AssignmentWarning()
{
// Warning CS8600: converting null literal or possible null value to non-nullable type.
string name = Lookup("nobody");
Console.WriteLine(name);
}
Si Lookup renvoie légitimement null, modifiez le site d’appel pour accepter la valeur manquante :
public static void AssignmentFixed()
{
string? name = Lookup("somebody");
if (name is not null)
{
Console.WriteLine(name);
}
}
Si Lookup ne retourne jamais null, modifiez sa signature pour qu’elle renvoie un type de référence non nullable. Scénarios où l’état null de la valeur retournée dépend de l’entrée, consultez la section suivante sur les attributs d’analyse null.
Utilisez l’opérateur null-forgiving ! uniquement lorsque vous pouvez garantir qu’une valeur n’est pas nulle, sans pouvoir exprimer cette garantie dans le système de types. Chacun ! d’eux est un endroit où le compilateur ne peut plus vous protéger, donc préférez ajouter une vérification ou annoter l’API source.
Ajouter un attribut d’analyse null
Parfois, le bon correctif n’est pas sur le site d’appel. La signature d’une méthode ne capture pas la relation entre ses entrées et ses sorties avec précision, et le compilateur émet des avertissements à l’intérieur d’un code sans risque :
public static bool IsPresent(string? text) =>
!string.IsNullOrEmpty(text);
public static void CallerWithoutAttribute(string? text)
{
if (IsPresent(text))
{
// Warning CS8602: dereference of a possibly null reference.
// The signature doesn't tell the compiler text is not-null here.
Console.WriteLine(text.Length);
}
}
Le corps de IsPresent prouve que l’argument n’est pas nul lorsque la méthode retourne true, mais la signature ne le dit pas. Ajoutez un attribut d’analyse nullable pour faire partie du contrat de l’API :
public static bool AttributedIsPresent([NotNullWhen(true)] string? text) =>
!string.IsNullOrEmpty(text);
public static void CallerWithAttribute(string? text)
{
if (AttributedIsPresent(text))
{
// No warning: the attribute tells the compiler text is not-null.
Console.WriteLine(text.Length);
}
}
Les attributs courants sont les suivants :
- NotNullWhenAttribute — l’argument n’est pas null lorsque la méthode retourne le booléen spécifié.
- NotNullIfNotNullAttribute : la valeur de retour n’est pas null chaque fois que l’argument nommé n’est pas null.
- MemberNotNullAttribute — les membres répertoriés sont non nuls après le retour de la méthode.
- DoesNotReturnAttribute — la méthode ne se termine jamais normalement (par exemple, elle lance toujours une exception).
La liste complète figure dans attributs Nullable pour l’analyse statique.
Initialiser des membres non nullables
Un avertissement du constructeur signifie qu’un champ, une propriété ou une propriété auto-implémentée non nullable (une propriété qui utilise le champ de stockage généré par le compilateur, comme public string Name { get; set; }) se termine sans qu’une valeur non nulle lui ait été affectée :
public class PersonUninitialized
{
// Warning CS8618: Non-nullable property 'Name' is uninitialized.
public string Name { get; set; }
}
Vous avez plusieurs façons de le traiter. Choisissez celui qui correspond le mieux à votre intention de conception.
Exiger la valeur comme argument du constructeur. Utilisez un constructeur principal (paramètres déclarés sur le type lui-même, disponibles dans le corps) ou un constructeur normal qui initialise la propriété :
public class PersonInjected(string name)
{
public string Name { get; } = name;
}
Définissez la propriété required. L’appelant doit l’initialiser via un initialiseur d’objet (la { Property = value } syntaxe suivante new) :
public class PersonRequired
{
public required string Name { get; init; }
}
Initialiser avec une valeur par défaut. Lorsque le type a une valeur vide significative, initialisez à la déclaration :
public class PersonInitialized
{
public string Name { get; set; } = "John Doe";
}
Conseil / Astuce
Choisissez cette technique uniquement lorsque le type possède une valeur par défaut réellement appropriée : une instance valide et entièrement fonctionnelle que le code appelant peut utiliser. Les exemples incluent des collections vides. N’utilisez pas de sentinelle (une valeur de remplacement telle que String.Empty, "N/A", "unknown" ou -1, que vous traitez comme « aucune valeur ») pour tenir lieu de null : cela supprime l’avertissement, mais chaque appelant doit connaître cette valeur sentinelle et la tester, et le système de types ne peut pas vous aider. Lorsqu’aucune valeur par défaut correcte n’existe, rendez la propriété nullable à la place.
Rendez la propriété nullable. Lorsque la valeur est vraiment manquante, remplacez le type par Nullable :
public class PersonOptional
{
public string? Name { get; set; }
}
Si une méthode auxiliaire initialise le membre, annotez la méthode auxiliaire avec MemberNotNullAttribute afin que le compilateur puisse prendre en compte les appels qui lui sont adressés.
Vérifier le paramètre du projet
Les nouveaux projets C# activent les types de référence nullables par défaut. Par conséquent, la plupart du code que vous écrivez ou lisez a déjà activé la fonctionnalité. Vous n’avez généralement pas besoin de configurer quoi que ce soit. Si vous êtes curieux de savoir si un projet l’a activé ou si vous devez modifier le paramètre, recherchez l’élément <Nullable> dans le .csproj:
<PropertyGroup>
<Nullable>enable</Nullable>
</PropertyGroup>
Les valeurs prises en charge courantes sont enable (la valeur par défaut pour les nouveaux projets) et disable. Si l’élément est manquant, le projet utilise la valeur par défaut définie par le SDK et le framework cible.
Si vous devez activer les types Nullable pour une partie seulement d’un fichier avec les directives #nullable, ou utiliser les modes partiels warnings et annotations lors de la migration d’une base de code existante, consultez stratégies de migration vers Nullable.
Quelle est la prochaine étape ?
Lorsqu’un avertissement ne correspond à aucun de ces modèles, l’article de référence sur les avertissements nullables résolus répertorie la technique pour chaque avertissement CS86xx émis par le compilateur.
Pour planifier une migration qui active progressivement les types de référence nullables dans une base de code existante, consultez les stratégies de migration Nullable.