1. Introduction
Imagine un peu : tu stockes des infos sur des chats dans ton code. Et tu veux, en plus de l'âge du chat par exemple, garder des états du genre "pas de données", "âge inconnu". Tu pourrais stocker 0, mais zéro — c'est un âge tout à fait valide.
int age = 0; // Âge du chat. Mais 0, c'est quoi ? Un chaton ou "inconnu" ?
Le souci, c'est que int prend que des valeurs entières, et "pas de données" n'existe pas dans les entiers. Si l'âge était une string, là tu pourrais mettre null. Mais avec les nombres, ça marche pas :
int age = null; // Erreur ! Impossible d'assigner null à une variable de type int
C'est parce que les types valeurs (les struct comme int, double, DateTime, bool) contiennent toujours quelque chose. Ils n'ont pas d'état "vide" (contrairement aux types référence, où null c'est juste l'absence d'objet).
Exemple dans la vraie vie :
Pour contourner cette limite, les devs inventent parfois des valeurs "spéciales" : genre -1 ou int.MaxValue pour "pas de valeur". Mais c'est moche, pas pratique et risqué : tu peux facilement confondre une vraie valeur avec un placeholder.
2. Type Nullable : un type qui peut être "null"
L'idée
Et si on permettait aux nombres normaux (et à tous les types valeurs en fait) de stocker non seulement une valeur, mais aussi null ?
En C#, c'est fait via une classe spéciale Nullable<T>. Cette classe peut contenir soit une valeur du type T, soit rien (donc null).
Syntaxe
int? age = null; // La variable age peut être un nombre ou null
Le compilateur C#, quand il voit ce code, il le comprend en fait comme :
Nullable<int> age = new Nullable<int>(); // La variable age ne contient pas de valeur
Ou, si tu veux mettre une valeur directe :
Nullable<int> age = new Nullable<int>(42); // age contient le nombre 42
Du coup, le point d'interrogation transforme n'importe quel type valeur en sa version nullable :
- int? (pareil que Nullable<int>)
- double?
- DateTime?
- et toutes les autres structs
Wrappers Nullable pour les structs les plus courants
| Type normal | Type Nullable | Exemple d'écriture |
|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
Tu peux aussi écrire la version longue avec la classe wrapper :
Nullable<int> pages = null;
Mais écrire int? — c'est plus court, donc plus cool.
3. Comment utiliser un type nullable
Affectation et vérification
L'affectation de null marche pareil que pour les types référence :
Déclaration et affectation
int? temperature = null;
temperature = 25;
Vérification de null
Comment savoir si notre type nullable a une vraie valeur ?
if (temperature != null)
{
Console.WriteLine($"Température : {temperature}");
}
else
{
Console.WriteLine("Pas de données sur la température");
}
Propriétés des types Nullable : .HasValue et .Value
Les types nullable ont deux propriétés importantes :
- .HasValue — renvoie true si la variable contient quelque chose (pas null).
- .Value — la valeur elle-même, si elle existe (sinon tu prends une exception).
int? temperature = null;
if (temperature.HasValue) //pas d'exception ici !
{
Console.WriteLine($"Température : {temperature.Value}°C");
}
else
{
Console.WriteLine("Température inconnue");
}
Ce code va marcher : temperature n'est pas null, il contient null à l'intérieur. Et tu peux toujours appeler la propriété HasValue sur un type Nullable. Mais essayer de choper .Value quand il n'y a rien — mauvaise idée, tu prends une exception InvalidOperationException. Vérifie toujours avant !
Syntaxe raccourcie pour l'affichage
Dans plein de cas, tu peux juste utiliser la variable nullable — et C# va gérer tout seul :
int? hours = null;
Console.WriteLine(hours); // affiche rien (juste vide)
hours = 10;
Console.WriteLine(hours); // affiche 10
4. Opérations et types nullable : arithmétique, comparaisons, conversions
Opérations : qu'est-ce qui se passe ?
Si un des opérandes est nullable, le résultat est aussi nullable.
Et si un des opérandes vaut null, le résultat est aussi null.
int? a = 5;
int? b = null;
int? sum = a + b; // sum == null
int? c = 10;
int? d = 15;
int? total = c + d; // total == 25
Opérations de comparaison
Tu peux comparer des types nullable avec des nombres normaux :
int? score = null;
if (score > 0) Console.WriteLine("Super résultat !");
else Console.WriteLine("Pas de résultat"); // C'est ce bloc qui va s'exécuter
Si score vaut null, la condition score > 0 sera false.
Conversion explicite et implicite
- Du type normal vers nullable : automatique.
- De nullable vers normal : seulement si c'est pas null (sinon exception).
int? x = 3;
int y = x.Value; // Ok si x n'est pas null
// Implicite
int? z = y;
5. Nullable et méthodes : paramètres et valeurs de retour
Retourner des valeurs nullable
Si une méthode ne peut pas toujours renvoyer un résultat, utilise un type nullable comme valeur de retour :
// La méthode cherche un utilisateur par login et renvoie son âge si trouvé, sinon null
int? FindUserAge(string login)
{
// ... ici la logique de recherche
return null; // si pas trouvé
}
Paramètres nullable
Tu peux accepter des valeurs nullable en paramètres, pour bien dire : “ça peut être là, ou pas”.
void PrintTemperature(int? temp)
{
if (temp == null)
Console.WriteLine("Température inconnue");
else
Console.WriteLine($"Température : {temp} degrés");
}
GO TO FULL VERSION