Warum ist der Standardwert des Zeichenfolgentyps null anstelle einer leeren Zeichenfolge?

218

Es ist ziemlich ärgerlich alle für meine Saiten zu testen , nullbevor ich Methoden sicher anwenden kann , wie ToUpper(), StartWith()etc ...

Wenn der Standardwert von stringdie leere Zeichenfolge wäre, müsste ich nicht testen, und ich würde das Gefühl haben, dass er mit den anderen Werttypen wie intoder doublezum Beispiel konsistenter ist . Zusätzlich Nullable<String>würde Sinn machen.

Warum haben sich die Designer von C # für die Verwendung nullals Standardwert für Zeichenfolgen entschieden?

Hinweis: Dies bezieht sich auf diese Frage , konzentriert sich jedoch mehr auf das Warum als auf das, was damit zu tun ist.

Marcel
quelle
53
Betrachten Sie dies als Problem für andere Referenztypen?
Jon Skeet
17
@ JonSkeet Nein, aber nur, weil ich anfangs fälschlicherweise dachte, dass Zeichenfolgen Werttypen sind.
Marcel
21
@Marcel: Das ist ein ziemlich guter Grund, sich darüber zu wundern.
TJ Crowder
7
@ JonSkeet Ja. Oh ja. (Aber Sie sind kein Fremder in der Diskussion über nicht nullbare Referenztypen…)
Konrad Rudolph
7
Ich glaube, Sie würden eine viel bessere Zeit haben, wenn Sie Behauptungen an Ihren Zeichenfolgen an Stellen verwenden würden, an denen Sie erwarten, dass sie NICHT vorliegen null(und ich empfehle Ihnen außerdem, nullZeichenfolgen konzeptionell als verschiedene Dinge zu behandeln und zu leeren). Ein Nullwert kann das Ergebnis eines Fehlers sein, während eine leere Zeichenfolge eine andere Bedeutung haben sollte.
Diegoreymendez

Antworten:

312

Warum ist der Standardwert des Zeichenfolgentyps null anstelle einer leeren Zeichenfolge?

Da stringist ein Referenztyp und der Standardwert für alle Referenztypen ist null.

Es ist ziemlich ärgerlich, alle meine Zeichenfolgen auf Null zu testen, bevor ich Methoden wie ToUpper (), StartWith () usw. sicher anwenden kann.

Dies steht im Einklang mit dem Verhalten von Referenztypen. Vor dem Aufrufen ihrer Instanzmitglieder sollte eine Überprüfung auf eine Nullreferenz vorgenommen werden.

Wenn der Standardwert der Zeichenfolge die leere Zeichenfolge wäre, müsste ich sie nicht testen, und ich würde der Meinung sein, dass sie mit den anderen Werttypen wie beispielsweise int oder double konsistenter ist.

Das Zuweisen des Standardwerts zu einem bestimmten Referenztyp null, der nicht inkonsistent wäre .

Zusätzlich Nullable<String>würde Sinn machen.

Nullable<T>arbeitet mit den Werttypen. Bemerkenswert ist die Tatsache, dass sie Nullablenicht auf der ursprünglichen .NET-Plattform eingeführt wurde, so dass es viel fehlerhaften Code gegeben hätte, wenn sie diese Regel geändert hätten. ( Mit freundlicher Genehmigung von @jcolebrand )

Habib
quelle
10
@HenkHolterman Man könnte eine ganze Menge Dinge implementieren, aber warum sollte man so eine krasse Inkonsistenz einführen?
4
@delnan - "warum" war hier die Frage.
Henk Holterman
8
@HenkHolterman Und "Konsistenz" ist die Widerlegung Ihres Punktes "Zeichenfolge könnte im Gegensatz zu anderen Referenztypen behandelt werden".
6
@delnan: Da ich an einer Sprache arbeite, die Zeichenfolgen als Werttypen behandelt, und mehr als 2 Jahre an Dotnet arbeite, stimme ich Henk zu. Ich sehe es als eine große FLAW auf Dotnet.
Fabricio Araujo
1
@delnan: Man könnte einen Werttyp erstellen, der sich im Wesentlichen wie folgt verhält String, mit Ausnahme von (1) dem werttypischen Verhalten, einen verwendbaren Standardwert zu haben, und (2) einer unglücklichen zusätzlichen Ebene der Box-Indirektion, wenn er angewendet wird Object. Angesichts der Tatsache, dass die Heap-Darstellung von stringeinzigartig ist, wäre eine spezielle Behandlung zur Vermeidung von zusätzlichem Boxen keine große Herausforderung gewesen (tatsächlich wäre es auch für andere Typen eine gute Sache, nicht standardmäßige Boxverhaltensweisen angeben zu können).
Supercat
40

Habib hat recht - weil stringes sich um einen Referenztyp handelt.

Noch wichtiger ist jedoch, dass Sie nichtnull jedes Mal nachsehen müssen, wenn Sie es verwenden. Sie sollten wahrscheinlich ArgumentNullExceptioneine nullReferenz werfen, wenn jemand Ihre Funktion übergibt .

Hier ist die Sache - das Framework würde NullReferenceExceptionsowieso ein für Sie werfen, wenn Sie versuchen würden, .ToUpper()eine Zeichenfolge aufzurufen . Denken Sie daran, dass dieser Fall auch dann auftreten kann, wenn Sie Ihre Argumente testen, nullda eine Eigenschaft oder Methode für die Objekte, die als Parameter an Ihre Funktion übergeben werden, ausgewertet werden kann null.

That being said, für leere Strings oder nulls Überprüfung eine gemeinsame Sache zu tun ist , so bieten sie String.IsNullOrEmpty()und String.IsNullOrWhiteSpace()nur für diesen Zweck.

Dave Markle
quelle
30
Sie sollten sich niemals selbst werfen NullReferenceException( msdn.microsoft.com/en-us/library/ms173163.aspx ); Sie werfen ein, ArgumentNullExceptionwenn Ihre Methode keine Null-Refs akzeptieren kann. Außerdem sind NullRefs normalerweise eine der schwierigeren Ausnahmen bei der Diagnose, wenn Sie Probleme beheben. Daher halte ich die Empfehlung, nicht auf Null zu prüfen, nicht für sehr gut.
Andy
3
@Andy "NullRefs sind normalerweise eine der am schwierigsten zu diagnostizierenden Ausnahmen" Ich stimme überhaupt nicht zu, wenn Sie Dinge protokollieren, ist es wirklich einfach zu finden und zu beheben (behandeln Sie einfach den Null-Fall).
Louis Kottmann
6
Das Werfen ArgumentNullExceptionhat den zusätzlichen Vorteil, dass der Parametername angegeben werden kann. Während des Debuggens spart dies ... ähm, Sekunden. Aber wichtige Sekunden.
Kos
2
@ DaveMarkle Sie möchten vielleicht IsNullOrWhitespace auch msdn.microsoft.com/en-us/library/…
Nathan Koop
1
Ich denke wirklich, dass das Überprüfen auf Null überall eine Quelle für immensen Code-Aufblähungen ist. Es ist hässlich und sieht hackig aus und es ist schwer, konsequent zu bleiben. Ich denke (zumindest in C # -ähnlichen Sprachen), dass eine gute Regel darin besteht, "das Null-Schlüsselwort im Produktionscode zu verbieten, es wie verrückt im Testcode zu verwenden".
Sara
24

Sie könnten eine Erweiterungsmethode schreiben (für das, was es wert ist):

public static string EmptyNull(this string str)
{
    return str ?? "";
}

Das funktioniert jetzt sicher:

string str = null;
string upper = str.EmptyNull().ToUpper();
Tim Schmelter
quelle
100
Aber bitte nicht. Das Letzte, was ein anderer Programmierer sehen möchte, sind Tausende von Codezeilen, die überall mit .EmptyNull () gespickt sind, nur weil der erste Typ vor Ausnahmen "Angst" hatte.
Dave Markle
15
@ DaveMarkle: Aber offensichtlich ist es genau das, wonach OP gesucht hat. "Es ist ziemlich ärgerlich, alle meine Zeichenfolgen auf Null zu testen, bevor ich Methoden wie ToUpper (), StartWith () usw. sicher anwenden kann"
Tim Schmelter
19
Der Kommentar ging an das OP, nicht an Sie. Während Ihre Antwort eindeutig richtig ist, sollte ein Programmierer, der eine grundlegende Frage wie diese stellt, dringend davor gewarnt werden, Ihre Lösung tatsächlich in die WIDE-Praxis umzusetzen, wie dies häufig der Fall ist. Es gibt eine Reihe von Kompromissen, die Sie in Ihrer Antwort nicht diskutieren, z. B. Undurchsichtigkeit, erhöhte Komplexität, Schwierigkeiten beim Refactoring, mögliche Überbeanspruchung von Erweiterungsmethoden und Ja, Leistung. Manchmal (oft) ist eine richtige Antwort nicht der richtige Weg, und deshalb habe ich kommentiert.
Dave Markle
5
@Andy: Die Lösung, wenn keine ordnungsgemäße Nullprüfung durchgeführt wird, besteht darin, ordnungsgemäß auf Nullen zu prüfen und ein Problem nicht mit einem Pflaster zu versehen.
Dave Markle
7
Wenn Sie Probleme beim Schreiben haben .EmptyNull(), verwenden Sie es (str ?? "")stattdessen einfach dort, wo es benötigt wird. Trotzdem stimme ich dem in @ DaveMarkles Kommentar zum Ausdruck gebrachten Gefühl zu: Sie sollten es wahrscheinlich nicht tun. nullund String.Emptysind konzeptionell unterschiedlich, und Sie können nicht unbedingt das gleiche wie das andere behandeln.
Ein CVn
17

Ab C # 6.0 können Sie auch Folgendes verwenden

string myString = null;
string result = myString?.ToUpper();

Das String-Ergebnis ist null.

Russelrillema
quelle
1
Um richtig zu sein, hat die Version der IDE seit c # 6.0 nichts damit zu tun, da dies eine Sprachfunktion ist.
Stijn Van Antwerpen
3
Eine andere Option -public string Name { get; set; } = string.Empty;
Jaja Harris
Wie heißt das? myString? .ToUpper ();
Hunter Nelson
1
Es wird als Null-Bedingter Operator bezeichnet. Sie können darüber hier lesen msdn.microsoft.com/en-us/magazine/dn802602.aspx
russelrillema
14

Leere Zeichenfolgen und Nullen unterscheiden sich grundlegend. Eine Null ist das Fehlen eines Werts und eine leere Zeichenfolge ist ein Wert, der leer ist.

Die Programmiersprache, die Annahmen über den "Wert" einer Variablen, in diesem Fall eine leere Zeichenfolge, trifft, ist so gut wie das Initiieren der Zeichenfolge mit einem anderen Wert, der kein Nullreferenzproblem verursacht.

Wenn Sie das Handle an diese Zeichenfolgenvariable an andere Teile der Anwendung übergeben, kann dieser Code nicht überprüfen, ob Sie absichtlich einen leeren Wert übergeben haben oder vergessen haben, den Wert dieser Variablen aufzufüllen.

Eine andere Möglichkeit, bei der dies ein Problem darstellen würde, besteht darin, dass die Zeichenfolge ein Rückgabewert einer Funktion ist. Da string ein Referenztyp ist und technisch einen Wert wie null und leer haben kann, kann die Funktion auch technisch null oder leer zurückgeben (nichts hindert sie daran). Da es nun zwei Begriffe für das "Fehlen eines Werts" gibt, dh eine leere Zeichenfolge und eine Null, muss der gesamte Code, der diese Funktion verwendet, zwei Überprüfungen durchführen. Einer für leer und der andere für null.

Kurz gesagt, es ist immer gut, nur eine Darstellung für einen einzelnen Staat zu haben. Weitere Informationen zu Leerzeichen und Nullen finden Sie unter den folgenden Links.

/software/32578/sql-empty-string-vs-null-value

NULL vs Leer beim Umgang mit Benutzereingaben

Nerrve
quelle
2
Und wie genau sehen Sie diesen Unterschied, etwa in einem Textfeld? Hat der Benutzer vergessen, einen Wert in das Feld einzugeben, oder lässt er ihn absichtlich leer? Null in einer Programmiersprache hat eine bestimmte Bedeutung. nicht zugewiesen. Wir wissen, dass es keinen Wert hat, der nicht mit einer Datenbank null identisch ist.
Andy
1
Es gibt keinen großen Unterschied, wenn Sie es mit einem Textfeld verwenden. In beiden Fällen ist es von größter Bedeutung, eine Notation zu haben, um das Fehlen eines Werts in einer Zeichenfolge darzustellen. Wenn ich einen auswählen müsste, würde ich null auswählen.
Nerrve
In Delphi ist string ein Werttyp und kann daher nicht null sein. In dieser Hinsicht macht es das Leben viel einfacher - ich finde es wirklich sehr ärgerlich, String zu einem Referenztyp zu machen.
Fabricio Araujo
1
Unter dem COM (Common Object Model) vor .net würde ein Zeichenfolgentyp entweder einen Zeiger auf die Daten der Zeichenfolge enthalten oder nulldie leere Zeichenfolge darstellen. Es gibt eine Reihe von Möglichkeiten, wie .net eine ähnliche Semantik hätte implementieren können, wenn sie sich dafür entschieden hätten, insbesondere angesichts Stringeiner Reihe von Merkmalen, die es ohnehin zu einem eindeutigen Typ machen [z. B. sind es und die beiden Array-Typen die einzigen Typen, deren Zuordnung Größe ist nicht konstant].
Supercat
7

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. Lengthals 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 Objectetwas trübe werden kann.

Ein alternativer Ansatz wäre gewesen, die Definition spezieller Strukturtypen zu ermöglichen, die nicht von geerbten, Objectsondern benutzerdefinierte Box- und Unboxing-Operationen erbten (die in einen anderen Klassentyp konvertiert wurden). Bei einem solchen Ansatz würde es einen Klassentyp geben, NullableStringder sich jetzt wie eine Zeichenfolge verhält, und einen Strukturtyp mit benutzerdefinierten Boxen String, der ein einzelnes privates Feld Valuevom Typ enthält String. Der Versuch, a Stringin NullableStringoder zu konvertieren , wird Objectzurückgegeben, Valuewenn er nicht null oder String.Emptynull ist. Beim Versuch, Stringin eine NullableStringInstanz umzuwandeln, die nicht null ist , wird die Referenz in Valuegespeichert (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.

Superkatze
quelle
1
Ich bin sehr froh, dass .NET als jemand spricht, der viel in SQL arbeitet und sich mit den Kopfschmerzen von Oracle befasst hat, ohne zwischen NULL und Nulllänge zu unterscheiden . "Leer" ist ein Wert, "null" nicht.
@ JonofAllTrades: Ich bin anderer Meinung. Im Anwendungscode gibt es keine Bedeutung dafür, dass eine Zeichenfolge als Klasse behandelt wird, außer beim Umgang mit Datenbankcode. Es ist ein Werttyp und ein grundlegender. Supercat: +1 an Sie
Fabricio Araujo
1
Datenbankcode ist eine große "Ausnahme". Solange es einige Problembereiche gibt, in denen Sie zwischen "vorhanden / bekannt, eine leere Zeichenfolge" und "nicht vorhanden / unbekannt / nicht anwendbar" unterscheiden müssen, z. B. Datenbanken, muss die Sprache dies unterstützen. Jetzt, wo .NET vorhanden ist Nullable<>, können Zeichenfolgen natürlich als Werttypen erneut implementiert werden. Ich kann nicht über die Kosten und den Nutzen einer solchen Wahl sprechen.
3
@ JonofAllTrades: Code, der sich mit Zahlen befasst, muss über ein Out-of-Band-Mittel verfügen, um den Standardwert Null von "undefiniert" zu unterscheiden. So wie es ist, muss nullfähiger Code, der mit Zeichenfolgen und Zahlen arbeitet, eine Methode für nullfähige Zeichenfolgen und eine andere für nullfähige Zahlen verwenden. Selbst wenn ein nullbarer Klassentyp stringeffizienter ist als Nullable<string>dies der Fall wäre, ist die Verwendung der "effizienteren" Methode aufwändiger als die Verwendung des gleichen Ansatzes für alle nullbaren Datendatenbankwerte.
Supercat
5

Da eine Zeichenfolgenvariable eine Referenz und keine Instanz ist .

Eine standardmäßige Initialisierung auf "Leer" wäre möglich gewesen, hätte jedoch auf der ganzen Linie viele Inkonsistenzen verursacht.

Henk Holterman
quelle
3
Es gibt keinen besonderen Grund, warum stringein Referenztyp sein müsste. Natürlich müssen die tatsächlichen Zeichen, aus denen die Zeichenfolge besteht, auf dem Heap gespeichert werden. Angesichts der Menge an dedizierter Unterstützung, die Zeichenfolgen bereits in der CLR haben, wäre es kein Problem, System.Stringein Werttyp mit a zu sein einzelnes privates Feld Valuevom Typ HeapString. Dieses Feld wäre ein Referenztyp und würde standardmäßig verwendet werden null, aber eine StringStruktur, deren ValueFeld null war, würde sich wie eine leere Zeichenfolge verhalten. Der einzige Nachteil dieses Ansatzes wäre ...
Supercat
1
... dass das Casting eines Stringto Objectin Abwesenheit von Sonderfallcode zur Laufzeit die Erstellung einer Box- StringInstanz auf dem Heap verursachen würde, anstatt einfach einen Verweis auf das zu kopieren HeapString.
Supercat
1
@supercat - niemand sagt, dass Zeichenfolge ein Werttyp sein sollte / könnte.
Henk Holterman
1
Niemand außer mir. Wenn die Zeichenfolge ein "spezieller" Wertetyp ist (mit einem privaten Referenztypfeld), kann die meiste Behandlung im Wesentlichen so effizient sein wie jetzt, mit Ausnahme einer zusätzlichen Nullprüfung für Methoden / Eigenschaften wie .Lengthusw., sodass Instanzen, die gelten Eine Nullreferenz würde nicht versuchen, sie zu dereferenzieren, sondern sich für eine leere Zeichenfolge entsprechend verhalten. Ob das Framework mit dieser stringImplementierung besser oder schlechter wäre , wenn man default(string)eine leere Zeichenfolge sein wollte ...
Supercat
1
... stringein Werttyp-Wrapper in einem Referenztyp-Feld zu sein, wäre der Ansatz, der die wenigsten Änderungen an anderen Teilen von .net erfordert [in der Tat, wenn man bereit wäre, eine Konvertierung von Stringzu akzeptieren , Objectum ein zusätzliches Element in einer Box zu erstellen, man könnte einfach Stringeine gewöhnliche Struktur mit einem Typfeld sein, Char[]das sie niemals enthüllte. Ich denke, ein HeapStringTyp wäre wahrscheinlich besser, aber in mancher Hinsicht wäre die Werttyp-Zeichenfolge mit a Char[]einfacher.
Supercat
5

Warum haben die Designer von C # null als Standardwert für Zeichenfolgen verwendet?

Da Zeichenfolgen Referenztypen sind , sind Referenztypen Standardwerte null. Variablen von Referenztypen speichern Verweise auf die tatsächlichen Daten.

Verwenden wir defaultfür diesen Fall das Schlüsselwort.

string str = default(string); 

strist a string, also ist es ein Referenztyp , also ist der Standardwert null.

int str = (default)(int);

strist ein int, also ist es ein Werttyp , also ist der Standardwert zero.

Soner Gönül
quelle
4

Wenn der Standardwert von stringdie leere Zeichenfolge wäre, müsste ich nicht testen

Falsch! Das Ändern des Standardwerts ändert nichts an der Tatsache, dass es sich um einen Referenztyp handelt und jemand die Referenz weiterhin explizit festlegen kann null.

Zusätzlich Nullable<String>würde Sinn machen.

Wahrer Punkt. Es wäre sinnvoller, nullkeine Referenztypen zuzulassen , sondern diese Funktion zu benötigen Nullable<TheRefType>.

Warum haben sich die Designer von C # für die Verwendung nullals Standardwert für Zeichenfolgen entschieden?

Konsistenz mit anderen Referenztypen. Warum überhaupt nullReferenztypen zulassen ? Wahrscheinlich, damit es sich wie C anfühlt, obwohl dies eine fragwürdige Entwurfsentscheidung in einer Sprache ist, die auch bietet Nullable.

Dan Burton
quelle
3
Es könnte sein, dass Nullable nur in .NET 2.0 Framework eingeführt wurde, also vorher nicht verfügbar war?
Jcolebrand
3
Vielen Dank an Dan Burton für den Hinweis, dass jemand den initialisierten Wert später bei Referenztypen auf null setzen kann. Wenn ich das durchdenke, weiß ich, dass meine ursprüngliche Absicht in der Frage zu keiner Verwendung führt.
Marcel
4

Wenn Sie ??beim Zuweisen Ihrer Zeichenfolgenvariablen den Operator verwenden, kann dies möglicherweise hilfreich sein.

string str = SomeMethodThatReturnsaString() ?? "";
// if SomeMethodThatReturnsaString() returns a null value, "" is assigned to str.
Amen Jlili
quelle
2

Ein String ist ein unveränderliches Objekt. Wenn ein Wert angegeben wird, wird der alte Wert nicht aus dem Speicher gelöscht, sondern verbleibt am alten Speicherort, und der neue Wert wird an einem neuen Speicherort abgelegt. Also , wenn der Standardwert String awar String.Empty, würde es den Abfall String.EmptyBlock im Speicher , wenn er seinen ersten Wert gegeben wurde.

Obwohl es winzig erscheint, kann es beim Initialisieren eines großen Arrays von Zeichenfolgen mit Standardwerten von zu einem Problem werden String.Empty. Natürlich können Sie immer die veränderbare StringBuilderKlasse verwenden, wenn dies ein Problem sein sollte.

djv
quelle
Vielen Dank, dass Sie die Sache mit der "ersten Initialisierung" erwähnt haben.
Marcel
3
Wie wäre es ein Problem beim Initialisieren eines großen Arrays? Da Strings, wie Sie sagten, unveränderlich sind, wären alle Elemente des Arrays einfach Zeiger auf dasselbe String.Empty. Irre ich mich
Dan Burton
2
Beim Standardwert für einen Typ werden alle Bits auf Null gesetzt. Die einzige Möglichkeit, dass der Standardwert stringeine leere Zeichenfolge ist, besteht darin, alle Bits Null als Darstellung einer leeren Zeichenfolge zuzulassen. Es gibt eine Reihe von Möglichkeiten, wie dies erreicht werden kann, aber ich denke nicht, dass es erforderlich ist, Verweise auf zu initialisieren String.Empty.
Supercat
Andere Antworten diskutierten diesen Punkt ebenfalls. Ich denke, die Leute sind zu dem Schluss gekommen, dass es keinen Sinn macht, die String-Klasse als Sonderfall zu behandeln und etwas anderes als All-Bit-Null als Initialisierung bereitzustellen, selbst wenn es so etwas wie String.Emptyoder wäre "".
DJV
@DanV: Das Ändern des Initialisierungsverhaltens von stringSpeicherorten hätte auch das Ändern des Initialisierungsverhaltens aller Strukturen oder Klassen mit Typfeldern erforderlich gemacht string. Dies würde eine ziemlich große Änderung im Design von .net darstellen, das derzeit erwartet, jeden Typ auf Null zu initialisieren, ohne darüber nachdenken zu müssen, was es ist, abgesehen von seiner Gesamtgröße.
Supercat
2

Da string ein Referenztyp ist und der Standardwert für den Referenztyp null ist.

Akshay
quelle
0

Vielleicht hat Sie das stringSchlüsselwort verwirrt, da es genau wie jede andere Werttypdeklaration aussieht , aber es ist tatsächlich ein Alias ​​für, System.Stringwie in dieser Frage erläutert .
Auch die dunkelblaue Farbe in Visual Studio und der Kleinbuchstabe können irreführen, wenn man denkt, dass es sich um eine handelt struct.

Alessandro Da Rugna
quelle
3
Gilt das nicht auch für das objectSchlüsselwort? Zugegeben, das wird weit weniger genutzt als string.
2
Da intist ein Alias ​​für System.Int32. Worauf willst du hinaus? :)
Thorarin
@Thorari @delnan: Sie beide Aliase sind, aber System.Int32ein Structso einen Standardwert, während System.Stringeine ist Classvon einem Zeiger mit Standardwert null. Sie werden visuell in derselben Schriftart / Farbe dargestellt. Ohne Wissen kann man denken, dass sie sich genauso verhalten (= einen Standardwert haben). Meine Antwort wurde mit einer kognitiven Psychologie-Idee von en.wikipedia.org/wiki/Cognitive_psychology dahinter geschrieben :-)
Alessandro Da Rugna
Ich bin mir ziemlich sicher, dass Anders Hejlsberg dies in einem Channel 9-Interview gesagt hat. Ich kenne den Unterschied zwischen Heap und Stack, aber die Idee mit C # ist, dass der Gelegenheitsprogrammierer das nicht muss.
Thomas Koelle
0

Nullable-Typen kamen erst in 2.0.

Wenn am Anfang der Sprache nullbare Typen erstellt worden wären, wäre die Zeichenfolge nicht nullwertfähig und die Zeichenfolge? wäre nullbar gewesen. Aufgrund der Abwärtskompatibilität konnten sie dies jedoch nicht tun.

Viele Leute sprechen über Ref-Typ oder nicht Ref-Typ, aber String ist eine ungewöhnliche Klasse und es wären Lösungen gefunden worden, um dies zu ermöglichen.

Thomas Koelle
quelle