Partager via


Types référence nullables (Référence C#)

Note

Cet article traite des types référence nullables. Vous pouvez également déclarer des types valeur nullables.

Vous pouvez utiliser des types de référence nullables dans le code qui se trouvent dans un contexte prenant en compte null. Les types référence nullables, les avertissements d’analyse statique null et l’opérateur null-forgiving sont des fonctionnalités de langage facultatives. Ils sont tous désactivés par défaut. Vous contrôlez un contexte nullable au niveau du projet à l’aide des paramètres de build ou du code à l’aide de pragmas.

Le langage C# documente la version la plus récente de la langue C#. Il contient également la documentation initiale des fonctionnalités dans les préversions publiques pour la prochaine version du langage.

La documentation identifie toute fonctionnalité introduite en premier dans les trois dernières versions de la langue ou dans les préversions publiques actuelles.

Conseil / Astuce

Pour savoir quand une fonctionnalité a été introduite en C#, consultez l’article sur l’historique des versions du langage C#.

Importante

Tous les modèles de projet activent par défaut le contexte nullable pour le projet. Les projets créés avec des modèles antérieurs n’incluent pas cet élément, et ces fonctionnalités sont désactivées, sauf si vous les activez dans le fichier projet ou si vous utilisez des pragmas.

Dans un contexte prenant en charge les types nullables :

  • Vous devez initialiser une variable d’un type T référence avec une valeur non null et vous ne pouvez jamais affecter une valeur qui peut être null.
  • Vous pouvez initialiser une variable d’un type T? référence avec null ou affecter null, mais vous devez la vérifier null avant de déreferencing.
  • Lorsque vous appliquez l’opérateur null-forgiving à une variable m de type T?, comme dans m!, la variable est considérée comme non null.

Le compilateur applique les distinctions entre un type T de référence non nullable et un type T? de référence nullable à l’aide des règles précédentes. Une variable de type T et une variable de type T? sont le même type .NET. L’exemple suivant déclare une chaîne non nullable et une chaîne nullable, puis utilise l’opérateur null-forgiving pour affecter une valeur à une chaîne non nullable :

string notNull = "Hello";
string? nullable = default;
notNull = nullable!; // null forgiveness

Les variables notNull et nullable les deux utilisent le String type. Étant donné que les types non nullables et nullables utilisent tous les deux le même type, vous ne pouvez pas utiliser de type référence nullable à plusieurs emplacements. En général, vous ne pouvez pas utiliser de type référence Nullable comme classe de base ou interface implémentée. Vous ne pouvez pas utiliser de type référence Nullable dans une expression de création ou de test de type d’objet. Vous ne pouvez pas utiliser de type référence nullable comme type d’expression d’accès aux membres. Les exemples suivants illustrent ces constructions :

public MyClass : System.Object? // not allowed
{
}

var nullEmpty = System.String?.Empty; // Not allowed
var maybeObject = new object?(); // Not allowed
try
{
    if (thing is string? nullableString) // not allowed
        Console.WriteLine(nullableString);
} catch (Exception? e) // Not Allowed
{
    Console.WriteLine("error");
}

Références nullables et analyse statique

Les exemples de la section précédente illustrent la nature des types référence nullables. Les types référence nullables ne sont pas de nouveaux types de classes, mais plutôt des annotations sur des types référence existants. Le compilateur utilise ces annotations pour vous aider à trouver des erreurs de référence null potentielles dans votre code. Il n’existe aucune différence de runtime entre un type référence non nullable et un type référence nullable. Le compilateur n’ajoute aucune vérification de runtime pour les types référence non nullables. Les avantages se trouvent dans l’analyse au moment de la compilation. Le compilateur génère des avertissements qui vous aident à rechercher et à corriger les erreurs null potentielles dans votre code. Vous déclarez votre intention et le compilateur vous avertit lorsque votre code contrevient à cette intention.

Importante

Les annotations de référence nullables n’introduisent pas de modifications de comportement, mais d’autres bibliothèques peuvent utiliser la réflexion pour produire différents comportements d’exécution pour les types de référence nullables et non nullables. Entity Framework Core lit notamment les attributs nullables. Il interprète une référence nullable comme une valeur facultative et une référence non nullable comme valeur obligatoire.

Dans un contexte prenant en charge les types nullables, le compilateur effectue une analyse statique sur des variables de n’importe quel type référence, nullable et non nullable. Le compilateur effectue le suivi de l’état null de chaque variable de référence comme not-null ou maybe-null. L’état par défaut d’une référence non nullable est not-null. L’état par défaut d’une référence nullable est maybe-null.

Les types référence non nullables doivent toujours pouvoir être déréférencés en toute sécurité, car leur état null est not-null. Pour appliquer cette règle, le compilateur émet des avertissements si un type référence non nullable n’est pas initialisé en valeur non-null. Vous devez affecter des variables locales où vous les déclarez. Chaque champ doit se voir attribuer une valeur not-null, dans un initialiseur de champ ou dans chaque constructeur. Le compilateur émet des avertissements quand une référence non nullable est affectée à une référence dont l’état est maybe-null. En règle générale, une référence non nullable n’est pas null et aucun avertissement n’est émis lorsque vous déférez ces variables.

Note

Si vous affectez une expression maybe-null à un type de référence non nullable, le compilateur génère un avertissement. Le compilateur génère ensuite des avertissements pour cette variable jusqu’à ce qu’elle soit affectée à une expression not-null.

Vous pouvez initialiser ou affecter null des types de référence nullables. Par conséquent, l’analyse statique doit déterminer qu’une variable est not-null avant d’être déréférencée. Si une référence nullable est déterminée comme étant peut-être null, l’affectation à une variable de référence non nullable génère un avertissement du compilateur. La classe suivante montre des exemples de ces avertissements :

public class ProductDescription
{
    private string shortDescription;
    private string? detailedDescription;

    public ProductDescription() // Warning! shortDescription not initialized.
    {
    }

    public ProductDescription(string productDescription) =>
        this.shortDescription = productDescription;

    public void SetDescriptions(string productDescription, string? details=null)
    {
        shortDescription = productDescription;
        detailedDescription = details;
    }

    public string GetDescription()
    {
        if (detailedDescription.Length == 0) // Warning! dereference possible null
        {
            return shortDescription;
        }
        else
        {
            return $"{shortDescription}\n{detailedDescription}";
        }
    }

    public string FullDescription()
    {
        if (detailedDescription == null)
        {
            return shortDescription;
        }
        else if (detailedDescription.Length > 0) // OK, detailedDescription can't be null.
        {
            return $"{shortDescription}\n{detailedDescription}";
        }
        return shortDescription;
    }
}

L’extrait de code suivant montre où le compilateur émet des avertissements lors de l’utilisation de cette classe :

string shortDescription = default; // Warning! non-nullable set to null;
var product = new ProductDescription(shortDescription); // Warning! static analysis knows shortDescription maybe null.

string description = "widget";
var item = new ProductDescription(description);

item.SetDescriptions(description, "These widgets will do everything.");

Les exemples précédents montrent comment l’analyse statique du compilateur détermine l’état null des variables de référence. Le compilateur applique des règles de langage pour les contrôles de valeur null et les affectations afin de guider son analyse. Le compilateur ne peut pas faire d’hypothèses sur la sémantique des méthodes ni des propriétés. Si vous appelez des méthodes qui effectuent des contrôles de valeur null, le compilateur ne peut pas savoir que ces méthodes affectent l’état null d’une variable. Vous pouvez ajouter des attributs à vos API pour informer le compilateur de la sémantique des arguments et des valeurs de retour. De nombreuses API courantes dans les bibliothèques .NET ont ces attributs. Par exemple, le compilateur interprète correctement IsNullOrEmpty comme une vérification null. Pour plus d’informations sur les attributs qui s’appliquent à l’analyse statique d’état null, consultez l’article sur les attributs nullables.

Définition du contexte nullable

Vous pouvez contrôler le contexte nullable de deux façons. Au niveau du projet, ajoutez le paramètre du <Nullable>enable</Nullable> projet. Dans un seul fichier source C#, ajoutez le #nullable enable pragma pour activer le contexte nullable. Consultez l’article sur la définition d’une stratégie nullable. Avant .NET 6, les nouveaux projets utilisent la valeur par défaut, <Nullable>disable</Nullable>. À partir de .NET 6, les nouveaux projets incluent l’élément <Nullable>enable</Nullable> dans le fichier projet.

spécification du langage C#

Pour plus d’informations, consultez la section Types de référence Nullable de la spécification du langage C#.

Voir aussi