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

Un type valeur Nullable T? représente toutes les valeurs de son type valeur sous-jacent T et une valeur null supplémentaire. Par exemple, vous pouvez assigner l’une des trois valeurs suivantes à une bool? variable : true , false ou null . Un type valeur sous-jacent T ne peut pas être un type valeur Nullable lui-même.

Notes

C# 8,0 introduit la fonctionnalité de types référence Nullable. Pour plus d’informations, consultez types de référence Nullable. Les types valeur Nullable sont disponibles à partir de C# 2.

Tout type valeur Nullable est une instance de la System.Nullable<T> structure générique. Vous pouvez faire référence à un type valeur Nullable avec un type sous-jacent T dans l’un des formulaires interchangeables suivants : Nullable<T> ou T? .

En général, vous utilisez un type valeur Nullable lorsque vous devez représenter la valeur indéfinie d’un type valeur sous-jacent. Par exemple, une variable booléenne, ou bool , ne peut être que true ou false . Toutefois, dans certaines applications, une valeur de variable peut être indéfinie ou manquante. Par exemple, un champ de base de données peut contenir true ou false , ou il ne peut contenir aucune valeur, autrement dit, NULL . Vous pouvez utiliser le bool? type dans ce scénario.

Déclaration et affectation

Comme un type valeur est implicitement convertible en type valeur Nullable correspondant, vous pouvez assigner une valeur à une variable d’un type valeur Nullable comme vous le feriez pour son type valeur sous-jacent. Vous pouvez également affecter la null valeur. Par exemple :

double? pi = 3.14;
char? letter = 'a';

int m2 = 10;
int? m = m2;

bool? flag = null;

// An array of a nullable value type:
int?[] arr = new int?[10];

La valeur par défaut d’un type valeur Nullable représente null , autrement dit, une instance dont la Nullable<T>.HasValue propriété retourne false .

Examen d’une instance d’un type valeur Nullable

À compter de C# 7,0, vous pouvez utiliser l' is opérateur avec un modèle de type pour examiner à la fois une instance d’un type de valeur Nullable pour null et récupérer une valeur d’un type sous-jacent :

int? a = 42;
if (a is int valueOfA)
{
    Console.WriteLine($"a is {valueOfA}");
}
else
{
    Console.WriteLine("a does not have a value");
}
// Output:
// a is 42

Vous pouvez toujours utiliser les propriétés en lecture seule suivantes pour examiner et obtenir la valeur d’une variable de type valeur Nullable :

L’exemple suivant utilise la HasValue propriété pour déterminer si la variable contient une valeur avant de l’afficher :

int? b = 10;
if (b.HasValue)
{
    Console.WriteLine($"b is {b.Value}");
}
else
{
    Console.WriteLine("b does not have a value");
}
// Output:
// b is 10

Vous pouvez également comparer une variable d’un type valeur Nullable avec null au lieu d’utiliser la HasValue propriété, comme le montre l’exemple suivant :

int? c = 7;
if (c != null)
{
    Console.WriteLine($"c is {c.Value}");
}
else
{
    Console.WriteLine("c does not have a value");
}
// Output:
// c is 7

Conversion d’un type valeur Nullable en un type sous-jacent

Si vous souhaitez assigner une valeur d’un type valeur Nullable à une variable de type valeur n’acceptant pas les valeurs NULL, vous devrez peut-être spécifier la valeur à assigner à la place de null . Utilisez l' opérateur ?? de fusion Null pour effectuer cette opération (vous pouvez également utiliser la Nullable<T>.GetValueOrDefault(T) méthode dans le même but) :

int? a = 28;
int b = a ?? -1;
Console.WriteLine($"b is {b}");  // output: b is 28

int? c = null;
int d = c ?? -1;
Console.WriteLine($"d is {d}");  // output: d is -1

Si vous souhaitez utiliser la valeur par défaut du type valeur sous-jacent à la place de null , utilisez la Nullable<T>.GetValueOrDefault() méthode.

Vous pouvez également effectuer un cast explicite d’un type valeur Nullable vers un type non Nullable, comme le montre l’exemple suivant :

int? n = null;

//int m1 = n;    // Doesn't compile
int n2 = (int)n; // Compiles, but throws an exception if n is null

Au moment de l’exécution, si la valeur d’un type valeur Nullable est null , le cast explicite lève une InvalidOperationException .

Un type valeur n’acceptant pas les valeurs null T est implicitement convertible en type valeur Nullable correspondant T? .

Opérateurs levés

Les opérateurs unaires et binaires prédéfinis ou tous les opérateurs surchargés pris en charge par un type valeur T sont également pris en charge par le type valeur Nullable correspondant T? . Ces opérateurs, également appelés opérateurs levés, produisent null si l’un des opérandes ou les deux sont null ; sinon, l’opérateur utilise les valeurs contenues de ses opérandes pour calculer le résultat. Par exemple :

int? a = 10;
int? b = null;
int? c = 10;

a++;        // a is 11
a = a * c;  // a is 110
a = a + b;  // a is null

Notes

Pour le bool? type, les opérateurs prédéfinis & et | ne suivent pas les règles décrites dans cette section : le résultat d’une évaluation d’opérateur peut être non null, même si l’un des opérandes est null . Pour plus d’informations, voir la section Opérateurs logiques booléens Nullable de l’article Opérateurs logiques booléens.

Pour les opérateurs de comparaison < , > , <= et >= , si l’un des opérandes ou les deux sont null , le résultat est false ; sinon, les valeurs contenues des opérandes sont comparées. Ne partez pas du principe que parce qu’une comparaison spécifique (par exemple <=) retourne false, la comparaison opposée (>) retourne true. L’exemple suivant montre que 10 n’est

  • ni supérieur ou égal à null
  • ni inférieur à null
int? a = 10;
Console.WriteLine($"{a} >= null is {a >= null}");
Console.WriteLine($"{a} < null is {a < null}");
Console.WriteLine($"{a} == null is {a == null}");
// Output:
// 10 >= null is False
// 10 < null is False
// 10 == null is False

int? b = null;
int? c = null;
Console.WriteLine($"null >= null is {b >= c}");
Console.WriteLine($"null == null is {b == c}");
// Output:
// null >= null is False
// null == null is True

Pour l' opérateur d’égalité == , si les deux opérandes sont null , le résultat est true , si un seul des opérandes est null , le résultat est false ; sinon, les valeurs contenues des opérandes sont comparées.

Pour l' opérateur d’inégalité != , si les deux opérandes sont null , le résultat est false , si un seul des opérandes est null , le résultat est true ; sinon, les valeurs contenues des opérandes sont comparées.

S’il existe une conversion définie par l’utilisateur entre deux types valeur, la même conversion peut également être utilisée entre les types valeur Nullable correspondants.

Boxing et unboxing

Une instance d’un type valeur Nullable T? est convertie comme suit :

  • Si HasValue retourne false, la référence null est générée.
  • Si HasValue retourne true , la valeur correspondante du type valeur sous-jacent T est boxed, et non l’instance de Nullable<T> .

Vous pouvez convertir une valeur boxed d’un type valeur T en type valeur Nullable correspondant T? , comme le montre l’exemple suivant :

int a = 41;
object aBoxed = a;
int? aNullable = (int?)aBoxed;
Console.WriteLine($"Value of aNullable: {aNullable}");

object aNullableBoxed = aNullable;
if (aNullableBoxed is int valueOfA)
{
    Console.WriteLine($"aNullableBoxed is boxed int: {valueOfA}");
}
// Output:
// Value of aNullable: 41
// aNullableBoxed is boxed int: 41

Comment identifier un type valeur Nullable

L’exemple suivant montre comment déterminer si une System.Type instance représente un type valeur Nullable construit, autrement dit, le System.Nullable<T> type avec un paramètre de type spécifié T :

Console.WriteLine($"int? is {(IsNullable(typeof(int?)) ? "nullable" : "non nullable")} value type");
Console.WriteLine($"int is {(IsNullable(typeof(int)) ? "nullable" : "non-nullable")} value type");

bool IsNullable(Type type) => Nullable.GetUnderlyingType(type) != null;

// Output:
// int? is nullable value type
// int is non-nullable value type

Comme le montre l’exemple, vous utilisez l’opérateur typeof pour créer une System.Type instance.

Si vous souhaitez déterminer si une instance est d’un type valeur Nullable, n’utilisez pas la Object.GetType méthode pour obtenir une Type instance à tester avec le code précédent. Quand vous appelez la Object.GetType méthode sur une instance d’un type valeur Nullable, l’instance est convertie en Object . La conversion boxing d’une instance non null d’un type valeur Nullable équivaut au boxing d’une valeur du type sous-jacent, GetType retourne une Type instance qui représente le type sous-jacent d’un type valeur Nullable :

int? a = 17;
Type typeOfA = a.GetType();
Console.WriteLine(typeOfA.FullName);
// Output:
// System.Int32

En outre, n’utilisez pas l’opérateur is pour déterminer si une instance est d’un type valeur Nullable. Comme le montre l’exemple suivant, vous ne pouvez pas distinguer les types d’une instance de type valeur Nullable et son instance de type sous-jacent avec l' is opérateur :

int? a = 14;
if (a is int)
{
    Console.WriteLine("int? instance is compatible with int");
}

int b = 17;
if (b is int?)
{
    Console.WriteLine("int instance is compatible with int?");
}
// Output:
// int? instance is compatible with int
// int instance is compatible with int?

Vous pouvez utiliser le code présenté dans l’exemple suivant pour déterminer si une instance est d’un type valeur Nullable :

int? a = 14;
Console.WriteLine(IsOfNullableType(a));  // output: True

int b = 17;
Console.WriteLine(IsOfNullableType(b));  // output: False

bool IsOfNullableType<T>(T o)
{
    var type = typeof(T);
    return Nullable.GetUnderlyingType(type) != null;
}

Notes

Les méthodes décrites dans cette section ne sont pas applicables dans le cas des types référence Nullable.

spécification du langage C#

Pour plus d’informations, consultez les sections suivantes de la spécification du langage C# :

Voir aussi