Dans .NET, il existe deux catégories de types: les références et les valeurs (int, double, structs, enums, etc.). Parmi leurs différences, il y a le fait qu'une référence peut être null
, alors qu'une valeur ne peut pas. Ainsi, si vous avez un type de valeur et que vous souhaitez transmettre une sémantique "facultative" ou "inconnue", vous pouvez l'orner avec Nullable<>
. Notez qu'il Nullable<>
est contraint par type à n'accepter que les types de valeur (il a une where T : struct
clause). Nullable<>
a également des avantages spéciaux du compilateur grâce auxquels une null
valeur est protégée contre NullReferenceExceptions
:
string x = null;
x.ToString(); // throws a NullReferenceException
int? y = null;
y.ToString(); // returns ""
Dans les langages fonctionnels (comme Scala, F #, Haskell, Swift, etc.), il est courant null
de ne pas exister . En effet, dans l'ensemble, les gens considèrent l'existence de null
comme une mauvaise idée , et les concepteurs de langage ont décidé de résoudre ce problème en le refusant.
Cela signifie que nous avons encore besoin d'un moyen de représenter une non-valeur dans ces langues. Entrez le Option
type (la nomenclature varie, cela s'appelle Maybe
en Haskell). Cela fait un travail similaire à Nullable
en ce qu'il encapsule un type pour ajouter le cas où la valeur est "Aucun" ou "Inconnu" etc.
La vraie différence réside dans les fonctions supplémentaires qui vous sont offertes par les langages qui implémentent Option
. À titre d'exemple, prenez Option.map
(en pseudocode):
function Option<T2> Option.map(opt: Option<T1>, mapFunc: T1 -> T2) {
if (opt is None) return None
else return Option<T2>(mapFunc(opt.Value))
}
Le chaînage de fonctions comme Option.map
est un moyen puissant d'éviter le passe-partout de vérification nulle typique que vous voyez partout en C #:
if (service == null)
return null;
var x = service.GetValue();
if (x == null || x.Property == null)
return null;
return x.Property.Value;
L'équivalent nul en C # serait:
public static Nullable<T2> Map<T1, T2>(this Nullable<T1> nullable, Func<T1, T2> f)
where T1 : struct
where T2 : struct
{
if (!nullable.HasValue) return (T2?)null;
else return (T2?) f(nullable.Value);
}
Cependant, cela a une utilité limitée en C # car cela ne fonctionnera que pour les types de valeur.
La nouvelle version de C # propose l'opérateur "propagation nulle" ( ?.
) qui est similaire à la Option.map
fonction sauf qu'il n'est applicable qu'aux méthodes et aux accesseurs de propriété. L'échantillon ci-dessus serait réécrit
return service?.GetValue()?.Property?.Value;