In .NET, ci sono due categorie di tipo: riferimenti e valori (int, double, struct, enums ecc.). Tra le loro differenze c'è il fatto che un riferimento può essere null
, mentre un valore non può. Pertanto, se si dispone di un tipo di valore e si desidera trasmettere una semantica "opzionale" o "sconosciuta", è possibile adornarlo Nullable<>
. Si noti che Nullable<>
è vincolato dal tipo per accettare solo i tipi di valore (ha una where T : struct
clausola). Nullable<>
ha anche vantaggi speciali dal compilatore per cui un null
valore è protetto da NullReferenceExceptions
:
string x = null;
x.ToString(); // throws a NullReferenceException
int? y = null;
y.ToString(); // returns ""
In linguaggi funzionali (come la Scala, F #, Haskell, Swift ecc) è comune per null
a non esiste . Questo perché nel complesso la gente considera l'esistenza di null
una cattiva idea e i progettisti del linguaggio hanno deciso di affrontare questo problema impedendolo.
Ciò significa che abbiamo di nuovo bisogno di un modo per rappresentare un valore in queste lingue. Inserisci il Option
tipo (la nomenclatura varia, si chiama Maybe
in Haskell). Questo fa un lavoro simile a Nullable
quello che avvolge un tipo per aggiungere il caso in cui il valore è "Nessuno" o "Sconosciuto" ecc.
La vera differenza sta nelle funzioni extra fornite dalle lingue che implementano Option
. Ad esempio, prendi Option.map
(in pseudocodice):
function Option<T2> Option.map(opt: Option<T1>, mapFunc: T1 -> T2) {
if (opt is None) return None
else return Option<T2>(mapFunc(opt.Value))
}
Il concatenamento di funzioni come Option.map
è un modo potente per evitare la tipica piastra di controllo null check che vedi ovunque in C #:
if (service == null)
return null;
var x = service.GetValue();
if (x == null || x.Property == null)
return null;
return x.Property.Value;
L'equivalente Nullable in C # sarebbe:
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);
}
Tuttavia, questo ha un'utilità limitata in C # perché funzionerà solo per i tipi di valore.
La nuova versione di C # offre l'operatore "null propagation" ( ?.
) che è simile alla Option.map
funzione tranne che è applicabile solo a metodi e accessori di proprietà. L'esempio sopra verrebbe riscritto
return service?.GetValue()?.Property?.Value;