Types référence Nullable (référence C#)

Notes

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

Les types référence nullables sont disponibles dans le code qui a choisi un contexte prenant en charge nullable. 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. Tous sont désactivés par défaut. Un contexte nullable est contrôlé au niveau du projet à l’aide des paramètres de build ou dans le code à l’aide de pragmas.

Important

Tous les modèles de projet commençant par .NET 6 (C# 10) activent 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 utilisez des pragmas.

Dans un contexte de prise en compte nullable :

  • Une variable d’un type T référence doit être initialisée avec une valeur non Null et ne peut jamais être affectée à une valeur qui peut être null.
  • Une variable d’un type T? référence peut être initialisée avec null ou affectée null, mais doit être vérifiée null avant de dé-référencer.
  • Une variable m de type T? est considérée comme non Null lorsque vous appliquez l’opérateur null-forgiving, comme dans m!.

Les distinctions entre un type T référence non Nullable et un type T? référence Nullable sont appliquées par l’interprétation du compilateur des règles précédentes. Une variable de type T et une variable de type T? sont représentées par 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 sont représentées par le String type. Étant donné que les types non Nullable et Nullable sont tous deux stockés comme le même type, il existe plusieurs emplacements où l’utilisation d’un type référence Nullable n’est pas autorisée. En général, un type référence nullable ne peut pas être utilisé comme une classe de base ou une interface implémentée. Un type référence nullable ne peut pas être utilisé dans une expression de création d’objet ou de test de type. Un type référence nullable ne peut pas être le type d’une expression d’accès de membre. 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 les 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 d’exécution entre un type référence non Nullable et un type référence nullable. Le compilateur n’ajoute aucune vérification du runtime pour les types référence non nullables. Les avantages sont dans l’analyse au moment de la compilation. Le compilateur génère des avertissements qui vous aident à trouver et à corriger les erreurs null potentielles dans votre code. Vous déclarez votre intention, et le compilateur vous avertit lorsque votre code enfreint cette intention.

Dans un contexte nullable activé, 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 non null ou peut-être null. L’état par défaut d’une référence non nullable n’est pas Null. L’état par défaut d’une référence nullable est peut-être null.

Les types référence non nullables doivent toujours être sécurisés pour la déréférence, car leur état null n’estpas 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. Les variables locales doivent être affectées là où elles sont déclarées. Chaque champ doit être affecté à une valeur non null , dans un initialiseur de champ ou chaque constructeur. Le compilateur émet des avertissements lorsqu’une référence non nullable est affectée à une référence dont l’état est peut-être null. En règle générale, une référence non nullable n’est pas null et aucun avertissement n’est émis lorsque ces variables sont déréférencées.

Notes

Si vous affectez une expression peut-être null à un type 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 non null .

Les types référence nullables peuvent être initialisés ou affectés à null. Par conséquent, l’analyse statique doit déterminer qu’une variable n’est pas null avant qu’elle ne soit déréférée. Si une référence nullable est déterminée à être peut-être null, l’affectation à une variable de référence non nullable génère un avertissement du compilateur. La classe suivante présente 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 vérifications et affectations Null pour informer son analyse. Le compilateur ne peut pas faire d’hypothèses sur la sémantique des méthodes ou des propriétés. Si vous appelez des méthodes qui effectuent des vérifications 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. Ces attributs ont été appliqués à de nombreuses API courantes dans les bibliothèques .NET Core. Par exemple, IsNullOrEmpty a été mis à jour et le compilateur interprète correctement cette méthode comme une vérification null. Pour plus d’informations sur les attributs qui s’appliquent à l’analyse statique à état Null, consultez l’article sur les attributs Nullable.

Définition du contexte nullable

Il existe deux façons de contrôler le contexte nullable. Au niveau du projet, vous pouvez ajouter le paramètre du <Nullable>enable</Nullable> projet. Dans un seul fichier source C#, vous pouvez ajouter 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> À compter 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 les propositions suivantes pour la spécification du langage C# :

Voir aussi