W .NET istnieją dwie kategorie typów: odwołania i wartości (int, double, structs, enums itp.). Wśród ich różnic jest fakt, że referencja może być null, podczas gdy wartość nie. Zatem jeśli masz typ wartości i chcesz przekazać „opcjonalną” lub „nieznaną” semantykę, możesz ją ozdobić Nullable<>. Zauważ, że Nullable<>jest ograniczony przez typ, aby akceptować tylko typy wartości (ma where T : structklauzulę). Nullable<>ma również specjalne afordancje od kompilatora, dzięki którym nullwartość jest chroniona przed NullReferenceExceptions:
string x = null;
x.ToString(); // throws a NullReferenceException
int? y = null;
y.ToString(); // returns ""
W językach funkcjonalnych (takich jak Scala, F #, Haskell, Swift itp) to jest wspólne dla nullcelu nie istnieje . Jest tak, ponieważ ogólnie ludzie uważają istnienie tego nullza zły pomysł , a projektanci języków postanowili rozwiązać ten problem, nie pozwalając mu na to.
Oznacza to, że ponownie potrzebujemy jakiegoś sposobu przedstawienia nie-wartości w tych językach. Wpisz Optiontyp (nomenklatura jest różna, nazywa się Maybew Haskell). Wykonuje to podobne zadanie Nullable, ponieważ otacza typ, aby dodać przypadek, w którym wartość to „Brak” lub „Nieznany” itp.
Prawdziwa różnica polega na tym, że dodatkowe funkcje są dostępne w implementowanych językach Option. Jako przykład weź Option.map(w pseudokodzie):
function Option<T2> Option.map(opt: Option<T1>, mapFunc: T1 -> T2) {
if (opt is None) return None
else return Option<T2>(mapFunc(opt.Value))
}
Łańcuchowe funkcje, takie jak, Option.mapto potężny sposób na uniknięcie typowej płyty kontrolnej zerowania, którą widzisz wszędzie w C #:
if (service == null)
return null;
var x = service.GetValue();
if (x == null || x.Property == null)
return null;
return x.Property.Value;
Nullable równoważne w C # byłoby:
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);
}
Jednak ma to ograniczoną użyteczność w języku C #, ponieważ będzie działać tylko dla typów wartości.
Nowa wersja C # oferuje operator „zerowej propagacji” ( ?.), który jest podobny do Option.mapfunkcji, z tą różnicą, że ma zastosowanie tylko do metod i akcesorów właściwości. Powyższa próbka zostanie przepisana
return service?.GetValue()?.Property?.Value;