it-swarm.com.de

Wenn null schlecht ist, warum implementieren moderne Sprachen es?

Ich bin sicher, dass Designer von Sprachen wie Java oder C # Probleme im Zusammenhang mit der Existenz von Nullreferenzen kannten (siehe Sind Nullreferenzen wirklich eine schlechte Sache? ) Der Optionstyp ist nicht viel komplexer als Nullreferenzen.

Warum haben sie beschlossen, es trotzdem aufzunehmen? Ich bin sicher, dass das Fehlen von Nullreferenzen einen besseren Code (insbesondere ein besseres Bibliotheksdesign) sowohl von Sprachentwicklern als auch von Benutzern fördern (oder sogar erzwingen) würde.

Liegt es einfach am Konservatismus - "andere Sprachen haben es, wir müssen es auch haben ..."?

84
mrpyo

Haftungsausschluss: Da ich keinen Sprachdesigner persönlich kenne, ist jede Antwort, die ich Ihnen gebe, spekulativ.

Von Tony Hoare selbst:

Ich nenne es meinen Milliardenfehler. Es war die Erfindung der Nullreferenz im Jahr 1965. Zu dieser Zeit entwarf ich das erste umfassende Typsystem für Referenzen in einer objektorientierten Sprache (ALGOL W). Mein Ziel war es sicherzustellen, dass jede Verwendung von Referenzen absolut sicher ist, wobei die Überprüfung automatisch vom Compiler durchgeführt wird. Aber ich konnte der Versuchung nicht widerstehen, eine Nullreferenz einzugeben, einfach weil es so einfach zu implementieren war. Dies hat zu unzähligen Fehlern und Schwachstellen geführt und Systemabstürze, die in den letzten vierzig Jahren wahrscheinlich eine Milliarde Dollar an Schmerzen und Schäden verursacht haben.

Hervorhebung von mir.

Natürlich schien es ihm damals keine schlechte Idee zu sein. Es ist wahrscheinlich, dass es teilweise aus demselben Grund verewigt wurde - wenn es dem mit dem Turing-Preis ausgezeichneten Erfinder von Quicksort als gute Idee erschien, ist es nicht verwunderlich, dass viele Leute immer noch nicht verstehen warum es böse ist. Zum Teil ist dies auch wahrscheinlich, weil es praktisch ist, dass neue Sprachen älteren Sprachen ähnlich sind, sowohl aus Marketing- als auch aus Lernkurvengründen. Ein typisches Beispiel:

"Wir waren hinter den C++ - Programmierern her. Wir haben es geschafft, viele von ihnen etwa auf halbem Weg zu LISP zu ziehen." Guy Steele, Co-Autor der Java spec

(Quelle: http://www.paulgraham.com/icad.html )

Und natürlich hat C++ null, weil C null hat, und es besteht keine Notwendigkeit, auf die historischen Auswirkungen von C einzugehen. C # hat J ++ abgelöst, was die Implementierung von Java durch Microsoft war, und es hat auch C++ als die Sprache der Wahl für die Windows-Entwicklung abgelöst, sodass es von beiden erhalten werden konnte.

[~ # ~] edit [~ # ~] Hier ist ein weiteres Zitat von Hoare, das es wert ist, in Betracht gezogen zu werden:

Programmiersprachen sind insgesamt sehr viel komplizierter als früher: Objektorientierung, Vererbung und andere Merkmale werden aus kohärenter und wissenschaftlicher Sicht immer noch nicht wirklich durchdacht Eine fundierte Disziplin oder eine Theorie der Korrektheit. Mein ursprüngliches Postulat, das ich mein ganzes Leben lang als Wissenschaftler verfolgt habe, ist, dass man die Kriterien der Korrektheit als Mittel zur Konvergenz auf a verwendet Anständiges Programmiersprachen-Design - eines, das seinen Benutzern keine Fallen stellt und in dem die verschiedenen Komponenten des Programms eindeutig den verschiedenen Komponenten seiner Spezifikation entsprechen, sodass Sie kompositorisch darüber nachdenken können. [...] Die Tools, einschließlich des Compilers, müssen auf einer Theorie basieren, was es bedeutet, ein korrektes Programm zu schreiben. Oral History Interview von Philip L. Frana, 17. Juli 2002, Cambridge, England; Charles Babbage Institute, Universität von Minnesota. [ http://www.cbi.umn.edu/oh/display.phtml?id=343]

Wieder meine Betonung. Sun/Oracle und Microsoft sind Unternehmen, und das Endergebnis eines Unternehmens ist Geld. Die Vorteile von null für sie haben möglicherweise die Nachteile aufgewogen, oder sie hatten einfach eine zu enge Frist, um das Problem vollständig zu prüfen. Als Beispiel für einen anderen Sprachfehler, der wahrscheinlich aufgrund von Fristen aufgetreten ist:

Es ist eine Schande, dass Cloneable kaputt ist, aber es passiert. Die ursprünglichen Java APIs wurden sehr schnell innerhalb einer engen Frist erstellt, um ein schließendes Marktfenster zu erreichen. Die ursprünglichen Java Team hat einen unglaublichen Job gemacht, aber nicht alle APIs sind perfekt. Klonbar ist eine Schwachstelle, und ich denke, die Leute sollten sich ihrer Grenzen bewusst sein. Josh Bloch

(Quelle: http://www.artima.com/intv/bloch13.html )

97
Doval

Ich bin sicher, dass Designer von Sprachen wie Java oder C # Probleme im Zusammenhang mit der Existenz von Nullreferenzen kannten

Na sicher.

Auch die Implementierung eines Optionstyps ist nicht viel komplexer als Nullreferenzen.

Ich bin anderer Ansicht! Die Entwurfsüberlegungen, die in C # 2 zu nullbaren Werttypen führten, waren komplex, kontrovers und schwierig. Sie haben die Designteams sowohl der Sprachen als auch der Laufzeit viele Monate lang diskutiert, Prototypen implementiert und so weiter, und tatsächlich wurde die Semantik des nullbaren Boxens sehr nahe am Versand von C # 2.0 geändert, was sehr kontrovers war.

Warum haben sie beschlossen, es trotzdem aufzunehmen?

Jedes Design ist ein Prozess der Auswahl unter vielen subtil und grob inkompatiblen Zielen; Ich kann nur eine kurze Skizze einiger der Faktoren geben, die berücksichtigt werden würden:

  • Die Orthogonalität von Sprachmerkmalen wird allgemein als eine gute Sache angesehen. C # hat nullbare Werttypen, nicht nullbare Werttypen und nullbare Referenztypen. Nicht nullfähige Referenztypen existieren nicht, wodurch das Typsystem nicht orthogonal ist.

  • Vertrautheit mit bestehenden Benutzern von C, C++ und Java ist wichtig.

  • Eine einfache Interoperabilität mit COM ist wichtig.

  • Eine einfache Interoperabilität mit allen anderen .NET-Sprachen ist wichtig.

  • Eine einfache Interoperabilität mit Datenbanken ist wichtig.

  • Die Konsistenz der Semantik ist wichtig; Wenn wir die Referenz TheKingOfFrance gleich null haben, bedeutet das immer "es gibt momentan keinen König von Frankreich" oder kann es auch bedeuten "Es gibt definitiv einen König von Frankreich; ich weiß nur nicht, wer es gerade ist"? oder kann es bedeuten "die Vorstellung, einen König in Frankreich zu haben, ist unsinnig, also stellen Sie nicht einmal die Frage!"? Null kann all diese Dinge und mehr in C # bedeuten, und all diese Konzepte sind nützlich.

  • Leistungskosten sind wichtig.

  • Es ist wichtig, für statische Analysen zugänglich zu sein.

  • Die Konsistenz des Typsystems ist wichtig; Können wir immer wissen, dass eine nicht nullbare Referenz nie unter irgendwelchen Umständen ungültig ist? Was ist mit dem Konstruktor eines Objekts mit einem nicht nullbaren Feld vom Referenztyp? Was ist mit dem Finalizer eines solchen Objekts, in dem das Objekt finalisiert wird weil der Code, der die Referenz ausfüllen sollte, eine Ausnahme auslöste? Ein Typensystem, das Sie über seine Garantien belügt, ist gefährlich.

  • Und was ist mit der Konsistenz der Semantik? Null Werte verbreiten sich bei Verwendung, aber null Referenzen lösen bei Verwendung Ausnahmen aus. Das ist inkonsistent; Ist diese Inkonsistenz durch einen gewissen Nutzen gerechtfertigt?

  • Können wir die Funktion implementieren, ohne andere Funktionen zu beschädigen? Welche anderen möglichen zukünftigen Funktionen schließt die Funktion aus?

  • Sie ziehen mit der Armee in den Krieg, die Sie haben, nicht mit der, die Sie möchten. Denken Sie daran, C # 1.0 hatte keine Generika, also sprechen Sie über Maybe<T> als Alternative ist ein kompletter Nichtstarter. Sollte .NET zwei Jahre lang verrutscht sein, während das Laufzeit-Team Generika hinzufügte, nur um Nullreferenzen zu beseitigen?

  • Was ist mit der Konsistenz des Typsystems? Sie können sagen Nullable<T> für jeden Werttyp - nein, warte, das ist eine Lüge. Sie können nicht sagen Nullable<Nullable<T>>. Solltest du dazu in der Lage sein? Wenn ja, welche Semantik ist erwünscht? Lohnt es sich, das gesamte Typsystem nur für diese Funktion mit einem Sonderfall zu versehen?

Und so weiter. Diese Entscheidungen sind komplex.

121
Eric Lippert

Null dient einem sehr gültigen Zweck, einen Wertmangel darzustellen.

Ich werde sagen, ich bin die lautstärkste Person, die ich über den Missbrauch von Null und all die Kopfschmerzen und Leiden kenne, die sie verursachen können, besonders wenn sie großzügig verwendet werden.

Meine persönliche Haltung ist, dass Menschen Nullen verwenden dürfen nur, wenn sie rechtfertigen können, dass dies notwendig und angemessen ist.

Beispiel zur Rechtfertigung von Nullen :

Das Todesdatum ist normalerweise ein nullbares Feld. Es gibt drei mögliche Situationen mit Todesdatum. Entweder ist die Person gestorben und das Datum ist bekannt, die Person ist gestorben und das Datum ist unbekannt, oder die Person ist nicht tot und daher existiert kein Todesdatum.

Das Todesdatum ist ebenfalls ein DateTime-Feld und hat keinen "unbekannten" oder "leeren" Wert. Es hat zwar das Standarddatum, das angezeigt wird, wenn Sie eine neue Datums-/Uhrzeitangabe erstellen, die je nach verwendeter Sprache variiert. Technisch gesehen besteht jedoch die Möglichkeit, dass die Person zu diesem Zeitpunkt tatsächlich gestorben ist und als "leerer Wert" gekennzeichnet wird, wenn Sie dies tun Verwenden Sie das Standarddatum.

Die Daten müssten die Situation richtig darstellen.

Person ist tot Todesdatum ist bekannt (09.03.1984)

Einfach, '09.03.1984'

Person ist tot Todesdatum ist unbekannt

Was ist das Beste? Null , '0/0/0000' oder '01/01/1869 '(oder was auch immer Ihr Standardwert ist?)

Person ist nicht tot Todesdatum ist nicht anwendbar

Was ist das Beste? Null , '0/0/0000' oder '01/01/1869 '(oder was auch immer Ihr Standardwert ist?)

Denken wir also über jeden Wert nach ...

  • Null , es hat Auswirkungen und Bedenken, vor denen Sie vorsichtig sein müssen. Ein versehentlicher Versuch, es zu manipulieren, ohne zu bestätigen, dass es nicht zuerst null ist, würde beispielsweise eine Ausnahme auslösen. aber es repräsentiert auch am besten die tatsächliche Situation ... Wenn die Person nicht tot ist, existiert das Todesdatum nicht ... es ist nichts ... es ist null ...
  • 0/0/0000 , Dies könnte in einigen Sprachen in Ordnung sein und könnte sogar eine angemessene Darstellung ohne Datum sein. Leider lehnen einige Sprachen und Validierungen dies als ungültige Datums-/Uhrzeitangabe ab, was in vielen Fällen ein No-Go bedeutet.
  • 01.01.1869 (oder was auch immer Ihr Standardwert für Datum/Uhrzeit ist) , das Problem hier ist, dass es schwierig wird, damit umzugehen. Sie könnten dies als Ihren Wertmangel verwenden, außer was passiert, wenn ich alle meine Datensätze herausfiltern möchte, für die ich kein Todesdatum habe? Ich könnte leicht Leute herausfiltern, die an diesem Datum tatsächlich gestorben sind, was zu Problemen mit der Datenintegrität führen könnte.

Tatsache ist, dass Sie manchmal Do nichts darstellen müssen und sicher, dass manchmal ein Variablentyp gut dafür funktioniert, aber häufig müssen Variablentypen in der Lage sein, nichts darzustellen.

Wenn ich keine Äpfel habe, habe ich 0 Äpfel, aber was ist, wenn ich nicht weiß, wie viele Äpfel ich habe?

Auf jeden Fall wird null missbraucht und ist möglicherweise gefährlich, aber es ist manchmal notwendig. In vielen Fällen ist dies nur die Standardeinstellung, denn bis ich einen Wert angegeben habe, fehlt ein Wert und etwas muss ihn darstellen. (Null)

28
RualStorge

Ich würde nicht so weit gehen wie "andere Sprachen haben es, wir müssen es auch haben ...", als wäre es eine Art, mit den Jones mitzuhalten. Ein wesentliches Merkmal jeder neuen Sprache ist die Fähigkeit, mit vorhandenen Bibliotheken in anderen Sprachen zusammenzuarbeiten (siehe: C). Da C Nullzeiger hat, benötigt die Interoperabilitätsschicht notwendigerweise das Konzept Null (oder ein anderes Äquivalent "existiert nicht", das bei Verwendung explodiert).

Der Sprachdesigner hätte wählen können, Optionstypen zu verwenden und Sie zu zwingen, den Nullpfad überall zu behandeln, wo Dinge null sein könnten . Und das würde mit ziemlicher Sicherheit zu weniger Fehlern führen.

Aber (insbesondere für Java und C # aufgrund des Zeitpunkts ihrer Einführung und ihrer Zielgruppe) hätte die Verwendung von Optionstypen für diese Interoperabilitätsschicht wahrscheinlich geschadet, wenn ihre Übernahme nicht torpediert worden wäre. Entweder ist der Optionstyp ging den ganzen Weg nach oben und nervte die C++ - Programmierer der mittleren bis späten 90er Jahre - oder die Interoperabilitätsschicht würde Ausnahmen auslösen, wenn sie auf Nullen stößt, und die C++ - Programmierer der mittleren bis späten 90er Jahre nerven ...

10
Telastyn

Zunächst denke ich, wir können uns alle einig sein, dass ein Konzept der Nichtigkeit notwendig ist. Es gibt einige Situationen, in denen wir das Fehlen von Informationen darstellen müssen.

Das Zulassen von null Referenzen (und Zeigern) ist nur eine Implementierung dieses Konzepts und möglicherweise die beliebteste, obwohl bekannt ist, dass Probleme auftreten: C, Java, Python, Ruby, PHP, JavaScript, ... alle verwenden ein ähnliches null.

Warum ? Was ist die Alternative?

In funktionalen Sprachen wie Haskell haben Sie den Typ Option oder Maybe; diese bauen jedoch auf:

  • parametrische Typen
  • algebraische Datentypen

Hat das ursprüngliche C, Java, Python, Ruby oder PHP eine dieser Funktionen unterstützt? Nein. Javas fehlerhafte Generika sind neu) in der Geschichte der Sprache und ich bezweifle irgendwie, dass die anderen sie überhaupt umsetzen.

Hier hast du es. null ist einfach, parametrische algebraische Datentypen sind schwieriger. Die Leute entschieden sich für die einfachste Alternative.

7
Matthieu M.

Null/Null/Keine selbst ist nicht böse.

Wenn Sie sich seine irreführend benannte berühmte Rede "The Billion Dollar Mistake" ansehen, spricht Tony Hoare darüber, wie groß es war, jeder Variablen zu erlauben, Null zu halten Fehler. Die Alternative - mit Optionen - entfernt nicht tatsächlich Nullreferenzen. Stattdessen können Sie angeben, welche Variablen null enthalten dürfen und welche nicht.

In modernen Sprachen, die eine ordnungsgemäße Ausnahmebehandlung implementieren, unterscheiden sich Null-Dereferenzierungsfehler nicht von anderen Ausnahmen - Sie finden sie, Sie beheben sie. Einige Alternativen zu Nullreferenzen (z. B. das Nullobjektmuster) verbergen Fehler, was dazu führt, dass Dinge bis viel später stillschweigend fehlschlagen. Meiner Meinung nach ist es viel besser, schnell zu scheitern .

Die Frage ist also, warum Sprachen Optionen nicht implementieren. Tatsächlich kann die wohl beliebteste Sprache aller Zeiten in C++ Objektvariablen definieren, denen NULL nicht zugewiesen werden kann. Dies ist eine Lösung für das in seiner Rede erwähnte "Null-Problem" Tony Hoare. Warum hat die nächstbeliebteste getippte Sprache, Java, diese nicht? Man könnte fragen, warum es so viele Fehler im Allgemeinen hat, insbesondere in seinem Typensystem. Ich glaube nicht, dass man wirklich sagen kann, dass Sprachen diesen Fehler systematisch machen. Einige tun es, andere nicht.

5
B T

Weil Programmiersprachen im Allgemeinen eher praktisch als technisch korrekt sind. Tatsache ist, dass null -Zustände häufig aufgrund fehlerhafter oder fehlender Daten oder eines noch nicht festgelegten Status auftreten. Die technisch überlegenen Lösungen sind alle unhandlicher, als einfach Nullzustände zuzulassen und die Tatsache aufzusaugen, dass Programmierer Fehler machen.

Wenn ich beispielsweise ein einfaches Skript schreiben möchte, das mit einer Datei funktioniert, kann ich Pseudocode wie folgt schreiben:

file = openfile("joebloggs.txt")

for line in file
{
  print(line)
}

und es wird einfach fehlschlagen, wenn joebloggs.txt nicht existiert. Die Sache ist, für einfache Skripte ist das wahrscheinlich in Ordnung und für viele Situationen in komplexerem Code weiß ich, dass es existiert und der Fehler nicht auftritt, so dass ich gezwungen bin, meine Zeit zu überprüfen. Die sichereren Alternativen erreichen ihre Sicherheit, indem sie mich zwingen, mit dem potenziellen Fehlerzustand richtig umzugehen, aber oft möchte ich das nicht tun, ich möchte einfach weitermachen.

4
Jack Aidley

Es gibt klare, praktische Verwendungen von NULL (oder nil oder Nil oder null oder Nothing oder was auch immer es ist in Ihrer bevorzugten Sprache aufgerufen) Zeiger.

Für diejenigen Sprachen, die kein Ausnahmesystem haben (z. B. C), kann ein Nullzeiger als Fehlermarke verwendet werden, wenn ein Zeiger zurückgegeben werden soll. Zum Beispiel:

char *buf = malloc(20);
if (!buf)
{
    perror("memory allocation failed");
    exit(1);
}

Hier wird ein von malloc(3) zurückgegebenes NULL als Fehlermarker verwendet.

Bei Verwendung in Methoden-/Funktionsargumenten kann angegeben werden, dass das Argument standardmäßig verwendet wird, oder dass das Ausgabeargument ignoriert wird. Beispiel unten.

Selbst für Sprachen mit Ausnahmemechanismus kann ein Nullzeiger als Hinweis auf einen weichen Fehler (dh Fehler, die behoben werden können) verwendet werden, insbesondere wenn die Ausnahmebehandlung teuer ist (z. B. Ziel-C):

NSError *err = nil;
NSString *content = [NSString stringWithContentsOfURL:sourceFile
                                         usedEncoding:NULL // This output is ignored
                                                error:&err];
if (!content) // If the object is null, we have a soft error to recover from
{
    fprintf(stderr, "error: %s\n", [[err localizedDescription] UTF8String]);
    if (!error) // Check if the parent method ignored the error argument
        *error = err;
    return nil; // Go back to parent layer, with another soft error.
}

Hier führt der weiche Fehler nicht zum Absturz des Programms, wenn es nicht abgefangen wird. Dies eliminiert den verrückten Try-Catch wie Java hat und hat eine bessere Kontrolle im Programmfluss, da weiche Fehler nicht unterbrochen werden (und die wenigen verbleibenden harten Ausnahmen normalerweise nicht wiederherstellbar sind und nicht erfasst werden).

4
Maxthon Chan

Es gibt zwei verwandte, aber leicht unterschiedliche Probleme:

  1. Sollte null überhaupt existieren? Oder sollten Sie immer Maybe<T> Verwenden, wo null nützlich ist?
  2. Sollten alle Referenzen nullbar sein? Wenn nicht, welches sollte die Standardeinstellung sein?

    Das explizite Deklarieren von nullfähigen Referenztypen als string? Oder ähnlich würde die meisten (aber nicht alle) Probleme vermeiden, die null verursacht, ohne sich zu stark von den gewohnten Programmierern zu unterscheiden.

Ich stimme Ihnen zumindest zu, dass nicht alle Referenzen nullbar sein sollten. Das Vermeiden von Null ist jedoch nicht ohne Komplexität:

.NET initialisiert alle Felder mit default<T>, Bevor sie zuerst von verwaltetem Code aufgerufen werden können. Dies bedeutet, dass Sie für Referenztypen null oder etwas Äquivalentes benötigen und dass Werttypen mit einer Art Null initialisiert werden können, ohne Code auszuführen. Während beide schwerwiegende Nachteile haben, kann die Einfachheit der Initialisierung von default diese Nachteile aufgewogen haben.

  • Für Instanzfelder können Sie dies umgehen, indem Sie die Initialisierung von Feldern erfordern, bevor Sie den Zeiger this für verwalteten Code verfügbar machen. Spec # ging diesen Weg und verwendete eine andere Syntax als die Konstruktorkettung im Vergleich zu C #.

  • Für statische Felder sicherstellen, dass dies schwieriger ist, es sei denn, Sie legen starke Einschränkungen für die Art des Codes fest, der in einem Feldinitialisierer ausgeführt werden kann, da Sie den Zeiger this nicht einfach ausblenden können.

  • Wie initialisiere ich Arrays von Referenztypen? Stellen Sie sich ein List<T> Vor, das von einem Array mit einer Kapazität unterstützt wird, die größer als die Länge ist. Die restlichen Elemente müssen einige Werte haben.

Ein weiteres Problem ist, dass Methoden wie bool TryGetValue<T>(key, out T value), die default(T) als value zurückgeben, nicht zugelassen werden, wenn sie nichts finden. In diesem Fall ist es jedoch leicht zu argumentieren, dass der out-Parameter in erster Linie ein schlechtes Design ist und diese Methode stattdessen eine diskriminierende Vereinigung oder ein vielleicht zurückgeben sollte.

Alle diese Probleme können gelöst werden, aber es ist nicht so einfach wie "Null verbieten und alles ist gut".

4
CodesInChaos

Die meisten nützlichen Programmiersprachen ermöglichen das Schreiben und Lesen von Datenelementen in beliebigen Sequenzen, so dass es häufig nicht möglich ist, die Reihenfolge, in der Lese- und Schreibvorgänge vor dem Ausführen eines Programms ausgeführt werden, statisch zu bestimmen. Es gibt viele Fälle, in denen Code tatsächlich nützliche Daten in jedem Slot speichert, bevor er gelesen wird, aber es ist schwierig zu beweisen, dass dies schwierig ist. Daher ist es häufig erforderlich, Programme auszuführen, bei denen es zumindest theoretisch möglich ist, dass Code versucht, etwas zu lesen, das noch nicht mit einem nützlichen Wert geschrieben wurde. Unabhängig davon, ob dies für Code zulässig ist oder nicht, gibt es keine allgemeine Möglichkeit, den Versuch des Codes zu verhindern. Die Frage ist nur, was passieren soll, wenn dies geschieht.

Unterschiedliche Sprachen und Systeme verfolgen unterschiedliche Ansätze.

  • Ein Ansatz wäre zu sagen, dass jeder Versuch, etwas zu lesen, das nicht geschrieben wurde, einen sofortigen Fehler auslöst.

  • Ein zweiter Ansatz besteht darin, zu verlangen, dass Code an jedem Ort einen Wert liefert, bevor er gelesen werden kann, selbst wenn der gespeicherte Wert nicht semantisch nützlich wäre.

  • Ein dritter Ansatz besteht darin, das Problem einfach zu ignorieren und alles, was "natürlich" passieren würde, einfach passieren zu lassen.

  • Ein vierter Ansatz besteht darin, zu sagen, dass jeder Typ einen Standardwert haben muss und jeder Slot, der mit nichts anderem geschrieben wurde, standardmäßig diesen Wert verwendet.

Ansatz Nr. 4 ist weitaus sicherer als Ansatz Nr. 3 und im Allgemeinen billiger als Ansatz Nr. 1 und Nr. 2. Dann bleibt die Frage, wie der Standardwert für einen Referenztyp lauten soll. Für unveränderliche Referenztypen wäre es in vielen Fällen sinnvoll, eine Standardinstanz zu definieren und zu sagen, dass der Standardwert für jede Variable dieses Typs eine Referenz auf diese Instanz sein sollte. Für veränderbare Referenztypen wäre dies jedoch nicht sehr hilfreich. Wenn versucht wird, einen veränderlichen Referenztyp zu verwenden, bevor er geschrieben wurde, gibt es im Allgemeinen keine sichere Vorgehensweise, außer zum Zeitpunkt der versuchten Verwendung abzufangen.

Semantisch gesehen wird die Ausführung ausgeführt, wenn man ein Array customers vom Typ Customer[20] Hat und versucht, Customer[4].GiveMoney(23), ohne etwas in Customer[4] Gespeichert zu haben einfangen. Man könnte argumentieren, dass ein Versuch, Customer[4] Zu lesen, sofort abgefangen werden sollte, anstatt zu warten, bis der Code versucht, GiveMoney zu lesen, aber es gibt genug Fälle, in denen es nützlich ist, einen Slot zu lesen, und herauszufinden, dass dies nicht der Fall ist Wenn Sie keinen Wert halten und dann diese Informationen verwenden, ist es oft ein großes Ärgernis, wenn der Leseversuch selbst fehlschlägt.

In einigen Sprachen kann angegeben werden, dass bestimmte Variablen niemals Null enthalten dürfen, und jeder Versuch, eine Null zu speichern, sollte eine sofortige Falle auslösen. Das ist eine nützliche Funktion. Im Allgemeinen muss jedoch jede Sprache, in der Programmierer Referenzarrays erstellen können, entweder die Möglichkeit von Null-Array-Elementen berücksichtigen oder die Initialisierung von Array-Elementen auf Daten erzwingen, die möglicherweise nicht aussagekräftig sind.

2
supercat