Warum erlauben die meisten "bekannten" Imperativ- / OO-Sprachen den ungeprüften Zugriff auf Typen, die einen Wert "nichts" darstellen können?

29

Ich habe über die (Un) Bequemlichkeit gelesen, nullstatt (zum Beispiel) zu haben Maybe. Nachdem ich diesen Artikel gelesen habe , bin ich überzeugt, dass es viel besser wäre, ihn zu verwendenMaybe (oder etwas Ähnliches). Ich bin jedoch überrascht zu sehen, dass alle "bekannten" imperativen oder objektorientierten Programmiersprachen weiterhin verwenden null(was den ungeprüften Zugriff auf Typen ermöglicht, die einen Wert "nichts" darstellen können) und dass dies Maybehauptsächlich in funktionalen Programmiersprachen verwendet wird.

Betrachten Sie als Beispiel den folgenden C # -Code:

void doSomething(string username)
{
    // Check that username is not null
    // Do something
}

Hier riecht etwas schlecht ... Warum sollten wir prüfen, ob das Argument null ist? Sollten wir nicht annehmen, dass jede Variable einen Verweis auf ein Objekt enthält? Wie Sie sehen, besteht das Problem darin, dass per Definition fast alle Variablen eine Nullreferenz enthalten können. Was wäre, wenn wir entscheiden könnten , welche Variablen "nullbar" sind und welche nicht? Das erspart uns viel Mühe beim Debuggen und Suchen einer "NullReferenceException". Stellen Sie sich vor, dass standardmäßig keine Typen eine Nullreferenz enthalten könnten . Stattdessen würden Sie explizit angeben, dass eine Variable nur dann eine Nullreferenz enthalten kann , wenn Sie sie wirklich benötigen. Das ist die Idee hinter Vielleicht. Wenn Sie eine Funktion haben, die in einigen Fällen fehlschlägt (z. B. Division durch Null), können Sie a zurückgebenMaybe<int>mit dem ausdrücklichen Hinweis, dass das Ergebnis ein int sein kann, aber auch nichts! Dies ist ein Grund, Vielleicht anstelle von Null zu bevorzugen . Wenn Sie an weiteren Beispielen interessiert sind, empfehle ich Ihnen, diesen Artikel zu lesen .

Die Tatsache ist, dass trotz der Nachteile, die es mit sich bringt, die meisten Typen standardmäßig auf null zu setzen, die meisten OO-Programmiersprachen dies tatsächlich tun. Deshalb frage ich mich über:

  • Welche Art von Argumenten würden Sie haben zu implementieren , nullanstatt in Ihrer Programmiersprache Maybe? Gibt es überhaupt Gründe oder handelt es sich nur um "historisches Gepäck"?

Bitte stellen Sie sicher, dass Sie den Unterschied zwischen null und Vielleicht verstehen, bevor Sie diese Frage beantworten.

aochagavia
quelle
3
Ich schlage vor, über Tony Hoare nachzulesen , insbesondere über seinen milliardenschweren Fehler.
Oded
2
Nun, das war sein Grund. Und das unglückliche Ergebnis ist, dass es ein Fehler war, der bis heute in die meisten folgenden Sprachen kopiert wurde. Es gibt Sprachen, in denen nulles kein Konzept gibt (IIRC Haskell ist ein solches Beispiel).
Oded
9
Historisches Gepäck ist nicht zu unterschätzen. Und denken Sie daran, dass die Betriebssysteme, auf denen diese basieren, in Sprachen geschrieben wurden, in denen nullsie schon seit langer Zeit vorkommen. Es ist nicht einfach, das einfach fallen zu lassen.
Oded
3
Ich denke, Sie sollten etwas Licht in das Konzept von Vielleicht bringen, anstatt einen Link zu posten.
JeffO
1
@ GlenH7 Strings in C # sind Referenzwerte (sie können null sein). Ich weiß, dass int ein primitiver Wert ist, aber es war nützlich, die Verwendung von maybe zu zeigen.
Aochagavia

Antworten:

15

Ich glaube, es ist hauptsächlich historisches Gepäck.

Die bekannteste und älteste Sprache mit nullist C und C ++. Aber hier nullmacht das Sinn. Zeiger sind immer noch ein ziemlich numerisches und einfaches Konzept. Und wie jemand anderes sagte, ist es in der Denkweise von C- und C ++ - Programmierern nullnicht sinnvoll , explizit zu sagen, dass Zeiger sein können .

An zweiter Stelle kommt Java. Da Java-Entwickler versucht haben, C ++ am nächsten zu kommen, um den Übergang von C ++ zu Java zu vereinfachen, wollten sie sich wahrscheinlich nicht mit einem solchen Kernkonzept der Sprache anlegen. Außerdem nullwürde das Implementieren von explizit viel mehr Aufwand erfordern, da Sie nach der Initialisierung überprüfen müssen, ob die Nicht-Null-Referenz tatsächlich richtig eingestellt ist.

Alle anderen Sprachen sind mit Java identisch. Sie kopieren normalerweise die Art und Weise, wie C ++ oder Java dies tun, und angesichts des Kernkonzepts impliziter nullVerweistypen wird es sehr schwierig, eine Sprache zu entwerfen, die explizit verwendet null.

Euphorisch
quelle
"Sie wollten sich wahrscheinlich nicht mit solch einem Kernkonzept der Sprache anlegen." Sie haben bereits Zeiger vollständig entfernt, und das Entfernen nullwäre auch keine große Veränderung, denke ich.
SVICK
2
@svick Bei Java sind Referenzen ein Ersatz für Zeiger. In vielen Fällen wurden Zeiger in C ++ genauso verwendet wie Java-Referenzen. Einige Leute behaupten sogar, dass Java Zeiger hat ( programmers.stackexchange.com/questions/207196/… )
Euphoric
Ich habe dies als die richtige Antwort markiert. Ich würde es gerne unterstützen, aber ich habe nicht genug Ruf.
Aochagavia
1
Zustimmen. Beachten Sie, dass es in C ++ (anders als in Java und C) die Ausnahme ist, nullfähig zu sein. std::stringkann nicht sein null. int&kann nicht sein null. An int*can und C ++ erlauben aus zwei Gründen den ungeprüften Zugriff darauf: 1. weil C dies getan hat und 2. weil Sie verstehen sollen, was Sie tun, wenn Sie in C ++ rohe Zeiger verwenden.
MSalters
@MSalters: Wenn ein Typ keinen bitkopierbaren Standardwert hat, muss zum Erstellen eines Arrays dieses Typs für jedes Element ein Konstruktor aufgerufen werden, bevor der Zugriff auf das Array selbst zugelassen wird. Dies kann unnötige Arbeit erfordern (wenn einige oder alle Elemente überschrieben werden, bevor sie gelesen werden), kann zu Komplikationen führen, wenn der Konstruktor für ein späteres Element fehlschlägt, nachdem ein früheres Element erstellt wurde, und kann ohnehin nicht wirklich viel bewirken (wenn Ein geeigneter Wert für einige Array-Elemente konnte nicht ermittelt werden, ohne andere zu lesen.
Supercat
15

Eigentlich nullist das eine tolle Idee. Bei einem gegebenen Zeiger möchten wir angeben, dass dieser Zeiger keinen gültigen Wert referenziert. Also nehmen wir einen Speicherort, erklären ihn für ungültig und halten uns an diese Konvention (eine Konvention, die manchmal mit Segfaults erzwungen wird). Wenn ich jetzt einen Zeiger habe, kann ich überprüfen, ob er Nothing( ptr == null) oder Some(value)( ptr != null, value = *ptr) enthält. Ich möchte, dass Sie verstehen, dass dies einem MaybeTyp entspricht.

Die Probleme dabei sind:

  1. In vielen Sprachen hilft das Typensystem hier nicht, eine Nicht-Null-Referenz zu garantieren.

    Dies ist historisches Gepäck, da viele gängige Imperativ- oder OOP-Sprachen im Vergleich zu ihren Vorgängern nur inkrementelle Fortschritte in ihren Typsystemen erzielt haben. Kleine Änderungen haben den Vorteil, dass neue Sprachen leichter zu lernen sind. C # ist eine Standardsprache, die Tools auf Sprachebene eingeführt hat, um mit Nullen besser umgehen zu können.

  2. API-Designer kehren möglicherweise nullbei einem Fehlschlag zurück, beziehen sich jedoch beim Erfolg nicht auf die eigentliche Sache. Oft wird die Sache (ohne Referenz) direkt zurückgegeben. Diese Abflachung einer Zeigerebene macht es unmöglich, sie nullals Wert zu verwenden.

    Dies ist nur eine Faulheit des Designers und kann nicht behoben werden, ohne eine ordnungsgemäße Verschachtelung mit einem ordnungsgemäßen Typsystem durchzusetzen. Einige Benutzer versuchen dies möglicherweise auch mit Überlegungen zur Leistung oder mit optionalen Überprüfungen zu rechtfertigen (eine Sammlung kann zurückgegeben werden nulloder das Element selbst, stellt jedoch auch eine containsMethode bereit ).

  3. In Haskell gibt es einen ordentlichen Blick auf den MaybeTyp als Monade. Dies erleichtert das Erstellen von Transformationen für den enthaltenen Wert.

    Auf der anderen Seite behandeln Low-Level-Sprachen wie C Arrays kaum als eigenen Typ, daher bin ich mir nicht sicher, was wir erwarten. In OOP-Sprachen mit parametrisiertem Polymorphismus ist ein zur Laufzeit überprüfter MaybeTyp eher trivial zu implementieren.

amon
quelle
"C # entfernt sich von Nullreferenzen." Welche Schritte sind das? Ich habe so etwas in den Sprachänderungen nicht gesehen. Oder meinen Sie nur, dass die gemeinsamen Bibliotheken nullweniger verwenden als in der Vergangenheit?
Svick
@svick Schlechte Phrasierung meinerseits. " C # ist einenull Standardsprache, die Tools auf Sprachebene eingeführt hat, um mit s besser umgehen zu können " - ich spreche über NullableTypen und den ??Standardoperator. Es löst das Problem im Moment nicht, wenn Legacy-Code vorhanden ist, aber es ist ein Schritt in Richtung einer besseren Zukunft.
amon
Ich stimme dir zu. Ich würde Ihre Antwort abstimmen, aber ich habe nicht genug Ruf :( Allerdings funktioniert Nullable nur für primitive Typen. Also ist es nur ein kleiner Schritt.
Aochagavia
1
@svick Nullable hat damit nichts zu tun. Wir sprechen über alle Referenztypen, die implizit einen Nullwert zulassen, anstatt dass der Programmierer ihn explizit definiert. Und Nullable kann nur für Werttypen verwendet werden.
Euphoric
@Euphoric Ich denke dein Kommentar war als Antwort auf amon gedacht, ich habe es nicht erwähnt Nullable.
Svick
9

Mein Verständnis ist, dass dies nullein notwendiges Konstrukt war, um Programmiersprachen aus der Assemblierung herauszuziehen. 1 Programmierer mussten angeben können, dass ein Zeiger- oder Registerwert der gebräuchliche Begriff für diese Bedeutung war not a valid valueund nullwurde.

Um den Punkt zu bekräftigen, der nullnur eine Konvention ist, um ein Konzept darzustellen, kann der tatsächliche Wert, der nullverwendet wird, je nach Programmiersprache und Plattform variieren.

Wenn Sie eine neue Sprache entwerfen und diese vermeiden, nullaber maybestattdessen verwenden möchten, würde ich einen aussagekräftigeren Begriff wie not a valid valueoder als Hinweis navvauf die Absicht empfehlen. Aber der Name des nicht-Wert ist ein separates Konzept aus , ob Sie sollten erlauben nicht-Werte auch in Ihrer Sprache vorhanden sind .

Bevor Sie sich für einen dieser beiden Punkte entscheiden können, müssen Sie definieren, was die Bedeutung maybefür Ihr System bedeuten würde. Sie stellen möglicherweise fest, dass es sich nur um eine Umbenennung der nullBedeutung von handelt, not a valid valueoder Sie stellen möglicherweise fest, dass es eine andere Semantik für Ihre Sprache hat.

Ebenso ist die Entscheidung, ob der Zugriff auf nullZugriff oder Verweis geprüft wird, eine andere Entwurfsentscheidung Ihrer Sprache.

Um ein wenig Geschichte zu Cerzählen, ging man implizit davon aus, dass Programmierer verstanden haben, was sie beim Manipulieren des Speichers zu tun versuchten. Da es sich um eine überlegene Abstraktion gegenüber der Assemblierung und den ihr vorausgegangenen Imperativsprachen handelte, war mir der Gedanke, den Programmierer vor einem falschen Verweis zu schützen, nicht in den Sinn gekommen.

Ich glaube, dass einige Compiler oder ihre zusätzlichen Tools eine Möglichkeit bieten, den ungültigen Zeigerzugriff zu überprüfen. Andere haben dieses potenzielle Problem erkannt und Maßnahmen zum Schutz dagegen ergriffen.

Ob Sie dies zulassen sollten oder nicht, hängt davon ab, was Ihre Sprache leisten soll und welchen Grad an Verantwortung Sie den Nutzern Ihrer Sprache übertragen möchten. Es hängt auch von Ihrer Fähigkeit ab, einen Compiler zu erstellen, um diese Art von Verhalten einzuschränken.

So beantworten Sie Ihre Fragen:

  1. "Welche Art von Argumenten ..." - Nun, es hängt davon ab, was die Sprache tun soll. Wenn Sie den Bare-Metal-Zugriff simulieren möchten, möchten Sie ihn möglicherweise zulassen.

  2. "Ist es nur historisches Gepäck?" Vielleicht vielleicht auch nicht. nullsicherlich hatte / hat Bedeutung für eine Reihe von Sprachen und hilft, den Ausdruck dieser Sprachen voranzutreiben. Der historische Präzedenzfall hat möglicherweise die neueren Sprachen und deren Zulassen beeinflusst, nullaber es ist ein bisschen viel, mit den Händen zu wedeln und das Konzept für nutzloses historisches Gepäck zu erklären.


1 Siehe diesen Wikipedia-Artikel, obwohl Hoare für Nullwerte und objektorientierte Sprachen anerkannt ist. Ich glaube, die imperativen Sprachen haben sich in einem anderen Stammbaum entwickelt als Algol.


quelle
Der Punkt ist, dass den meisten Variablen in C # oder Java eine Nullreferenz zugewiesen werden kann. Es sieht so aus, als ob es viel besser wäre, Null-Referenzen nur Objekten zuzuweisen, die explizit anzeigen, dass "Vielleicht" keine Referenz vorhanden ist. Meine Frage bezieht sich also auf das "Konzept" null und nicht auf das Wort.
Aochagavia
2
„Nullzeigerreferenzen können während des Kompilierens als Fehler angezeigt werden.“ Welche Compiler können das?
Svick
Um ganz fair zu sein, weisen Sie einem Objekt niemals eine Nullreferenz zu ... die Referenz auf das Objekt existiert einfach nicht (die Referenz zeigt auf nichts (0x000000000), was per Definition ist null).
mgw854
Das Zitat der C99-Spezifikation spricht vom Null-Zeichen , nicht vom Null-Zeiger . Das sind zwei sehr unterschiedliche Konzepte.
SVICK
2
@ GlenH7 Das macht es nicht für mich. Der Code wird object o = null; o.ToString();für mich ohne Fehler oder Warnungen in VS2012 einwandfrei kompiliert. ReSharper beschwert sich darüber, aber das ist nicht der Compiler.
SVICK
7

Wenn Sie sich die Beispiele in dem Artikel ansehen, den Sie zitiert haben, Maybeverkürzt die meiste Zeit die Verwendung des Codes nicht. Dies macht eine Überprüfung nicht überflüssig Nothing. Der einzige Unterschied ist, dass Sie über das Typensystem daran erinnert werden, dies zu tun.

Beachten Sie, ich sage "erinnern", nicht erzwingen. Programmierer sind faul. Wenn ein Programmierer davon überzeugt ist, dass ein Wert unmöglich sein kann Nothing, wird er den Wert dereferenzieren, Maybeohne ihn zu überprüfen, genau wie er jetzt einen Nullzeiger dereferenziert. Das Endergebnis ist, dass Sie eine Nullzeigerausnahme in eine "dereferenzierte leere Vielleicht" -Ausnahme konvertieren.

Dasselbe Prinzip der menschlichen Natur gilt auch in anderen Bereichen, in denen Programmiersprachen versuchen, Programmierer zu etwas zu zwingen. Zum Beispiel versuchten die Java-Designer, die meisten Ausnahmen zu verarbeiten, was zu einer großen Anzahl von Ausnahmen führte, die entweder unbemerkt ignoriert oder blindlings weitergegeben wurden.

Was macht, Maybeist schön, wenn viele Entscheidungen über Pattern Matching und Polymorphismus statt expliziter Prüfungen getroffen werden. Sie könnten beispielsweise separate Funktionen erstellen processData(Some<T>)und processData(Nothing<T>), mit denen Sie nichts anfangen können null. Sie verschieben Ihre Fehlerbehandlung automatisch in eine separate Funktion, was bei der funktionalen Programmierung sehr wünschenswert ist, wenn Funktionen nicht immer von oben nach unten aufgerufen werden, sondern nur schleppend weitergegeben und ausgewertet werden. In OOP ist die bevorzugte Methode zum Entkoppeln des Fehlerbehandlungscodes mit Ausnahmen.

Karl Bielefeldt
quelle
Denken Sie, dass dies in einer neuen OO-Sprache wünschenswert wäre?
Aochagavia
Sie können es selbst implementieren, wenn Sie die Vorteile des Polymorphismus nutzen möchten. Das einzige, wofür Sie Sprachunterstützung benötigen, ist die Nichtnullierbarkeit. Ich würde gerne einen Weg finden, dies für sich selbst zu spezifizieren, ähnlich wie const, aber optional zu machen. Einige Arten von Code auf niedrigerer Ebene, wie beispielsweise verknüpfte Listen, wären bei der Implementierung mit nicht nullwertfähigen Objekten sehr ärgerlich.
Karl Bielefeldt
2
Sie müssen jedoch nicht mit dem Typ Vielleicht nachsehen. Der Typ "Vielleicht" ist eine Monade, daher sollten die Funktionen map :: Maybe a -> (a -> b) und bind :: Maybe a -> (a -> Maybe b)Definitionen darauf enthalten sein, damit Sie mit der Neufassung mit einer if else-Anweisung weitere Berechnungen fortsetzen und einfädeln können. Und getValueOrDefault :: Maybe a -> (() -> a) -> aermöglicht es Ihnen, den nullbaren Fall zu behandeln. Es ist weitaus eleganter als der Maybe aexplizite Mustervergleich .
DetriusXii
1

Maybeist eine sehr funktionale Denkweise für ein Problem - es gibt etwas, und es kann einen definierten Wert haben oder nicht. Im objektorientierten Sinne ersetzen wir jedoch die Idee eines Dings (egal ob es einen Wert hat oder nicht) durch ein Objekt. Ein Objekt hat eindeutig einen Wert. Wenn nicht, sagen wir, das Objekt ist null, aber wir meinen wirklich, dass es überhaupt kein Objekt gibt. Der Verweis, den wir auf das Objekt haben, zeigt auf nichts. Die Übersetzung Maybein ein OO-Konzept ist nichts Neues - in der Tat sorgt es nur für eine größere Code-Unordnung. Sie müssen immer noch eine Nullreferenz für den Wert von habenMaybe<T>. Sie müssen immer noch Nullprüfungen durchführen (in der Tat müssen Sie viel mehr Nullprüfungen durchführen, was Ihren Code überfrachtet), auch wenn sie jetzt "Vielleichtprüfungen" heißen. Sicher, Sie werden robusteren Code schreiben, wie der Autor behauptet, aber ich würde argumentieren, dass dies nur der Fall ist, weil Sie die Sprache weitaus abstrakter und stumpfer gemacht haben, was in den meisten Fällen einen unnötigen Arbeitsaufwand erfordert. Ich mache ab und zu gerne eine NullReferenceException, bevor ich mich mit Spaghetti-Code beschäftige, der bei jedem Zugriff auf eine neue Variable eine Vielleicht-Prüfung durchführt.

mgw854
quelle
2
Ich denke, dass dies zu weniger Nullprüfungen führen würde, da Sie nur prüfen müssen, ob Sie ein Vielleicht <T> sehen und sich nicht um den Rest der Typen kümmern müssen.
Aochagavia
1
@svick Maybe<T>muss nullals Wert erlauben , da der Wert möglicherweise nicht existiert. Wenn ich habe Maybe<MyClass>und es keinen Wert hat, muss das Wertfeld eine Nullreferenz enthalten. Es gibt nichts anderes, was nachweislich sicher ist.
mgw854
1
@ mgw854 Klar gibt es. In der OO-Sprache Maybekönnte es sich um eine abstrakte Klasse handeln, von der zwei Klassen erben: Some(die ein Feld für den Wert enthält) und None(die dieses Feld nicht enthält). Auf diese Weise ist der Wert nie null.
SVICK
6
Mit der Standardeinstellung "nicht nullbar" und <T> können Sie sicher sein, dass einige Variablen immer Objekte enthalten. Nämlich alle Variablen, die nicht Vielleicht <T>
aochagavia
3
@ mgw854 Der Punkt dieser Änderung wäre eine erhöhte Ausdruckskraft für Entwickler. Derzeit muss der Entwickler immer davon ausgehen, dass die Referenz oder der Zeiger null sein kann, und muss überprüfen, ob ein verwendbarer Wert vorhanden ist. Durch die Implementierung dieser Änderung geben Sie dem Entwickler die Befugnis, zu sagen, dass er wirklich einen gültigen Wert benötigt, und lassen den Compiler überprüfen, um sicherzustellen, dass ein gültiger Wert übergeben wurde. Aber es gibt dem Entwickler immer noch die Möglichkeit, sich anzumelden und keinen Wert weiterzugeben.
Euphoric
1

Das Konzept von nulllässt sich leicht auf C zurückführen, aber hier liegt nicht das Problem.

Meine Alltagssprache ist C # und ich würde nullmit einem Unterschied bleiben . C # hat zwei Arten von Typen, Werten und Referenzen . Werte können niemals sein null, aber es gibt Zeiten, in denen ich gerne ausdrücken möchte, dass kein Wert vollkommen in Ordnung ist. Um dies zu tun, verwendet C # NullableTypen, also intden Wert und int?den nullbaren Wert. So sollten meiner Meinung nach auch Referenztypen funktionieren.

Siehe auch: Nullreferenz darf kein Fehler sein :

Null-Referenzen sind hilfreich und manchmal unverzichtbar (überlegen Sie, wie viel Mühe Sie haben, wenn Sie eine Zeichenfolge in C ++ zurückgeben oder nicht). Der Fehler liegt nicht in der Existenz der Nullzeiger, sondern in der Art und Weise, wie das Typsystem mit ihnen umgeht. Leider behandeln die meisten Sprachen (C ++, Java, C #) sie nicht richtig.

Daniel Little
quelle
0

Ich denke, das liegt daran, dass sich die funktionale Programmierung sehr um Typen kümmert , insbesondere um Typen, die andere Typen (Tupel, Funktionen als erstklassige Typen, Monaden usw.) kombinieren als die objektorientierte Programmierung (oder zumindest anfangs).

Moderne Versionen der Programmiersprachen (C ++, C #, Java) basieren alle auf Sprachen, die keine generische Programmierung hatten (C, C # 1.0, Java 1). Ohne das können Sie immer noch einen Unterschied zwischen nullbaren und nicht nullbaren Objekten in die Sprache schreiben (wie C ++ - Referenzen, die nicht möglich null, aber auch begrenzt sind), aber es ist viel weniger natürlich.

svick
quelle
Ich denke, im Falle der funktionalen Programmierung ist es der Fall, dass FP keine Referenz- oder Zeigertypen hat. In FP ist alles ein Wert. Und wenn Sie einen Zeigertyp haben, wird es leicht, "Zeiger auf nichts" zu sagen.
Euphoric
0

Ich denke, der Hauptgrund ist, dass relativ wenige Nullprüfungen erforderlich sind, um ein Programm "sicher" gegen Datenkorruption zu machen. Wenn ein Programm versucht, den Inhalt eines Array-Elements oder eines anderen Speicherorts zu verwenden, der mit einer gültigen Referenz geschrieben sein soll, dies aber nicht war, wird im besten Fall eine Ausnahme ausgelöst. Im Idealfall gibt die Ausnahme genau an, wo das Problem aufgetreten ist. Entscheidend ist jedoch, dass eine Art Ausnahme ausgelöst wird, bevor die Nullreferenz an einer Stelle gespeichert wird, die zu einer Beschädigung der Daten führen kann. Wenn eine Methode ein Objekt nicht speichert, ohne es zuerst in irgendeiner Weise zu verwenden, stellt der Versuch, ein Objekt zu verwenden, an und für sich eine Art "Nullprüfung" dar.

Wenn sichergestellt werden soll, dass eine Nullreferenz, die an der Stelle angezeigt wird, an der sie nicht auftreten sollte, eine andere Ausnahme hervorruft als NullReferenceException, müssen häufig überall Nullprüfungen eingefügt werden. Auf der anderen Seite erfordert das bloße Sicherstellen, dass eine Ausnahme auftritt, bevor eine Nullreferenz einen "Schaden" hervorruft, der über die bereits durchgeführten hinausgeht, häufig relativ wenige Tests - Tests wären im Allgemeinen nur in Fällen erforderlich, in denen ein Objekt eine Verweis, ohne zu versuchen, ihn zu verwenden, und entweder würde der Null-Verweis einen gültigen überschreiben, oder es würde dazu führen, dass anderer Code andere Aspekte des Programmstatus falsch interpretiert. Solche Situationen existieren, sind aber nicht allzu häufig. Die meisten versehentlichen Nullreferenzen werden sehr schnell abgefangenob man nach ihnen sucht oder nicht .

Superkatze
quelle
Dieser Beitrag ist ziemlich schwer zu lesen (Textwand). Hätten Sie etwas dagegen bearbeiten sie in eine bessere Form ing?
gnat
1
@gnat: Ist das besser?
Supercat
0

" Maybe," wie geschrieben, ist ein höheres Konstrukt als null. Wenn Sie mehr Wörter verwenden, um es zu definieren, lautet es möglicherweise: "Ein Zeiger auf eine Sache oder ein Zeiger auf nichts, aber der Compiler hat noch nicht genügend Informationen erhalten, um zu bestimmen, welche." Dies zwingt Sie dazu, jeden Wert ständig explizit zu überprüfen, es sei denn, Sie erstellen eine Compilerspezifikation, die intelligent genug ist, um mit dem von Ihnen geschriebenen Code Schritt zu halten.

Sie können eine Implementierung von "Vielleicht" mit einer Sprache vornehmen, die leicht Nullen enthält. C ++ hat eine in Form von boost::optional<T>. Das Äquivalent von null mit Vielleicht ist sehr schwierig. Insbesondere wenn ich a habe Maybe<Just<T>>, kann ich es nicht null zuweisen (da ein solches Konzept nicht existiert), während es T**in einer Sprache mit null sehr einfach ist, null zuzuweisen. Dies erzwingt die Verwendung eines Maybe<Maybe<T>>Objekts, was völlig gültig ist. Sie werden jedoch dazu gezwungen, weitere Überprüfungen durchzuführen, um dieses Objekt zu verwenden.

Einige funktionale Sprachen verwenden Vielleicht, weil null entweder undefiniertes Verhalten oder Ausnahmebehandlung erfordert, was kein einfaches Konzept ist, um Syntaxen für funktionale Sprachen zuzuordnen. Vielleicht füllt die Rolle in solchen funktionalen Situationen viel besser aus, aber in prozeduralen Sprachen ist null König. Es geht nicht um Richtig und Falsch, sondern nur darum, was es einfacher macht, dem Computer zu sagen, was er tun soll.

Cort Ammon - Setzen Sie Monica wieder ein
quelle