Was ist der Unterschied zwischen Optionals und dem Typ Nullable?

12

Swift hat Optionals. C # hat NullableTypen.

Soweit ich weiß, dienen beide demselben Zweck und speichern neben dem Wert eines bestimmten Typs auch Informationen darüber, ob eine Variable einen Wert hat oder nicht definiert (nicht initialisiert) ist.

Die Frage ist, ob es sich Optionalsnur um NullableTypen mit unterschiedlichen Namen handelt oder ob es andere konzeptionelle Unterschiede gibt.

Mit anderen Worten, wenn Sie über das Konzept selbst sprechen oder im Kontext von Sprachen, die nicht über Optionalsoder verfügen Nullables, spielt es eine Rolle, welcher Begriff verwendet wird?

Bei der Implementierung dieser Funktionalität in Sprache spielt es eine Rolle, ob ich type Optionals<T>oder bezeichneNullable<T>

Dalija Prasnikar
quelle
Aus sprachunabhängiger Sicht sind sie identisch. Das heißt, eine Sprache kann die Konzepte unterscheiden (z. B. ob der Mustervergleich erzwungen wird oder nicht).
Thomas Eding
C # kann auch Optionen haben (es ist nur ein monadisches Muster): github.com/louthy/language-ext
Den
2
Die Verwendung einer Nullreferenz (oder eines NULL-Zeigers in Sprachen mit Zeigern) ist ein Hack, den einige Sprachen verwenden, um optionale Werte darzustellen, dh einen Container, der einen Wert oder gar keinen Wert haben kann. Dies hat die Einschränkung, dass Sie nur einen Typ als optional betrachten können, der auf Referenzen (oder Zeigern) basiert. So können Sie beispielsweise in Java eine Ganzzahl nicht optional machen, ohne sie in ein Objekt (z. B. eine Ganzzahl) zu packen. Andere Sprachen bieten optionale Typen als generische Typen, die jeden anderen Typ umschließen können, z. B. Vielleicht in Haskell, Option in Scala und so weiter.
Giorgio

Antworten:

5

Es gibt eine andere Konnotation, obwohl sie sehr ähnlich funktionieren. Jeder außer Microsoft (hier Eye-Roll einfügen) nutzt nullund nullablenur im Rahmen von Referenzen. Optionsund Maybeses wird allgemein verstanden, dass sie sich sowohl auf Referenzen als auch auf Werte beziehen, insbesondere in funktionalen Programmiersprachen, in denen referenzielle Transparenz bedeutet, dass es keinen großen Unterschied zwischen einem Wert und einer Referenz gibt.

Mit anderen Worten, über das Konzept selbst zu sprechen oder im Kontext von Sprachen, die nicht über Optionalsoder verfügen Nullables, spielt es eine Rolle, welcher Begriff verwendet wird?

Optionsist der Begriff, der bei einem breiten Publikum am wenigsten Verwirrung stiftet. Nur C # -Programmierer werden sich einen Nullableals potenziell auf einen Werttyp zutreffend vorstellen, und ich denke, die meisten von ihnen sind sich zumindest dessen bewusst, was ein Wert Optionist.

Karl Bielefeldt
quelle
Jeder außer Microsoft und den Designern von SQL, denke ich, du meinst.
Jules,
9

In .NET gibt es zwei Kategorien von Typen: Referenzen und Werte (int, double, structs, enums usw.). Zu ihren Unterschieden gehört die Tatsache, dass eine Referenz sein kann null, während ein Wert dies nicht kann. Wenn Sie also einen Wertetyp haben und "optionale" oder "unbekannte" Semantik übermitteln möchten, können Sie ihn mit schmücken Nullable<>. Beachten Sie, dass Nullable<>typabhängig nur Werttypen zulässig sind (es gibt eine where T : structKlausel). Nullable<>hat auch spezielle Vergünstigungen vom Compiler, wodurch ein nullWert geschützt ist vor NullReferenceExceptions:

string x = null;
x.ToString(); // throws a NullReferenceException

int? y = null;
y.ToString(); // returns ""

In funktionalen Sprachen (wie Scala, F #, Haskell, Swift usw.) ist es üblich, dass nullsie nicht existieren . Dies liegt daran, dass die Existenz von im Großen und Ganzen nullals eine schlechte Idee angesehen wird und die Sprachdesigner beschlossen haben, dieses Problem zu lösen, indem sie es nicht zulassen.

Dies bedeutet, dass wir in diesen Sprachen wieder eine Möglichkeit benötigen, einen Nicht-Wert darzustellen . Geben Sie den OptionTyp ein (die Nomenklatur variiert, Maybein Haskell heißt sie). Dies ist insofern ähnlich Nullable, als es einen Typ umschließt, um den Fall hinzuzufügen, in dem der Wert "Keine" oder "Unbekannt" usw. ist.

Der wahre Unterschied liegt in den zusätzlichen Funktionen, die Ihnen von den implementierten Sprachen zur Verfügung gestellt werden Option. Nehmen Sie als Beispiel Option.map(in 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))
}

Verkettungsfunktionen wie Option.mapsind eine leistungsstarke Methode, um das typische Null-Check-Boilerplate zu vermeiden, das Sie überall in C # sehen:

if (service == null)
    return null;
var x = service.GetValue();
if (x == null || x.Property == null)
    return null;
return x.Property.Value;

Das Nullable-Äquivalent in C # wäre:

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);
}

Dies ist jedoch in C # nur eingeschränkt nützlich, da es nur für Werttypen funktioniert.

Die neue Version von C # bietet den Operator "Null-Propagation" ( ?.), der der Option.mapFunktion ähnlich ist, außer dass er nur für Methoden und Eigenschafts-Accessoren gilt. Das obige Beispiel würde neu geschrieben

return service?.GetValue()?.Property?.Value;
AlexFoxGill
quelle
C # ist eine unreine funktionale Sprache (genau wie F #). Auch F # hat Nullen.
Den
C # 6 hat Nullwertzwang, daher ist zumindest ein Teil Ihres Codes nicht aktuell: github.com/dotnet/roslyn/wiki/… roslyn.codeplex.com/discussions/540883
Den
Auch Optionen sind einfach zu implementieren: github.com/louthy/language-ext
Den
1
@Den: C # neigt sich zu OOP, während F # sich zu FP neigt. Standardmäßig ist C # nicht für ernsthafte funktionale Programmierung geeignet. Ich erwähnte die Null-Propagierung am Ende der Antwort. Optionen sind in der Tat einfach in C # zu implementieren, aber das weicht von der Frage ab.
AlexFoxGill
4
@Den ich denke, es gibt einige schlechte Wortwahl in Ihren Kommentaren. Eine unreine funktionale Sprache ist eine funktionale Sprache, die Nebenwirkungen zulässt. C # kann einige Funktionsmerkmale haben und Sie können sie mit großer Wirkung einsetzen, aber es ist keine Funktionssprache. Ich vermute, Sie meinten, dass keine der beiden Sprachen 100% funktionsfähig ist, aber F # steht OCaml sehr nahe. Unabhängig davon, welche Abweichungen es vom Funktionsparadigma macht, gibt es meistens Abweichungen, sodass es mit fremdem .NET-Code zusammenarbeiten kann. In diesem Fall nullist kein gültiger Wert für F # -Typen.
Doval