In .NET, ci sono due categorie di tipi: riferimenti e valori (int, double, structs, enum ecc.). Tra le loro differenze c'è il fatto che un riferimento può essere null , mentre un valore non può. Quindi se hai un tipo di valore e vuoi trasmettere una semantica "opzionale" o "sconosciuta", puoi adornarla con Nullable<> . Nota che Nullable<> è vincolato dal tipo per accettare solo i tipi di valore (ha una clausola where T : struct ). Nullable<> ha anche accessi speciali dal compilatore per cui un valore null è protetto da NullReferenceExceptions :
string x = null;
x.ToString(); // throws a NullReferenceException
int? y = null;
y.ToString(); // returns ""
Nei linguaggi funzionali (come Scala, F #, Haskell, Swift ecc.) è comune per null a non esiste . Questo perché nel complesso le persone considerano l'esistenza di null come un cattiva idea , e i progettisti di linguaggi hanno deciso di risolvere questo problema disabilitandolo.
Ciò significa che ancora una volta abbiamo bisogno di un modo per rappresentare un non-valore in queste lingue. Inserisci il tipo Option (la nomenclatura varia, è chiamata Maybe in Haskell). Questo fa un lavoro simile a Nullable in quanto avvolge un tipo per aggiungere il caso in cui il valore è "Nessuno" o "Sconosciuto" ecc.
La vera differenza è nelle funzioni extra fornite da 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 funziona come Option.map è un modo efficace per evitare il tipico tagliando di controllo nullo 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 con i tipi di valore.
La nuova versione di C # offre l'operatore "propagazione nulla" ( ?. ) che è simile alla funzione Option.map , eccetto che è applicabile solo per metodi e accessi di proprietà. L'esempio precedente verrebbe riscritto
return service?.GetValue()?.Property?.Value;