Der grundlegende Grund / das grundlegende Problem besteht darin, dass die Designer der CLS-Spezifikation (die definiert, wie Sprachen mit .net interagieren) kein Mittel definiert haben, mit dem Klassenmitglieder festlegen können, dass sie direkt und nicht über aufgerufen werden müssen callvirt
, ohne dass der Aufrufer a ausführt Nullreferenzprüfung; Es bot auch keine Möglichkeit, Strukturen zu definieren, die keinem "normalen" Boxen unterliegen würden.
Hätte die CLS-Spezifikation ein solches Mittel definiert, wäre es für .net möglich, konsequent dem vom Common Object Model (COM) festgelegten Vorsprung zu folgen, unter dem eine Nullzeichenfolgenreferenz als semantisch äquivalent zu einer leeren Zeichenfolge angesehen wurde, und für andere Benutzerdefinierte unveränderliche Klassentypen, die eine Wertsemantik haben sollen, um ebenfalls Standardwerte zu definieren. Was im Wesentlichen passieren würde, wäre, dass jedes Mitglied von String
, z. B. Length
als so etwas geschrieben wird [InvokableOnNull()] int String Length { get { if (this==null) return 0; else return _Length;} }
. Dieser Ansatz hätte eine sehr schöne Semantik für Dinge geboten, die sich wie Werte verhalten sollten, aber aufgrund von Implementierungsproblemen auf dem Heap gespeichert werden müssen. Die größte Schwierigkeit bei diesem Ansatz besteht darin, dass die Semantik der Konvertierung zwischen solchen Typen Object
etwas trübe werden kann.
Ein alternativer Ansatz wäre gewesen, die Definition spezieller Strukturtypen zu ermöglichen, die nicht von geerbten, Object
sondern benutzerdefinierte Box- und Unboxing-Operationen erbten (die in einen anderen Klassentyp konvertiert wurden). Bei einem solchen Ansatz würde es einen Klassentyp geben, NullableString
der sich jetzt wie eine Zeichenfolge verhält, und einen Strukturtyp mit benutzerdefinierten Boxen String
, der ein einzelnes privates Feld Value
vom Typ enthält String
. Der Versuch, a String
in NullableString
oder zu konvertieren , wird Object
zurückgegeben, Value
wenn er nicht null oder String.Empty
null ist. Beim Versuch, String
in eine NullableString
Instanz umzuwandeln, die nicht null ist , wird die Referenz in Value
gespeichert (möglicherweise wird null gespeichert, wenn die Länge null ist). Das Wirken einer anderen Referenz würde eine Ausnahme auslösen.
Obwohl Zeichenfolgen auf dem Heap gespeichert werden müssen, gibt es konzeptionell keinen Grund, warum sie sich nicht wie Werttypen verhalten sollten , die einen Standardwert ungleich Null haben. Wenn sie als "normale" Struktur gespeichert worden wären, die eine Referenz enthielt, wäre dies für Code, der sie als Typ "Zeichenfolge" verwendete, effizient gewesen, hätte jedoch beim Umwandeln in "Objekt" eine zusätzliche Ebene der Indirektion und Ineffizienz hinzugefügt. Obwohl ich nicht vorsehe, dass .net zu diesem späten Zeitpunkt eine der oben genannten Funktionen hinzufügt, könnten Designer zukünftiger Frameworks in Betracht ziehen, sie einzubeziehen.