string.Empty vs null.Welches verwenden Sie?


83

Kürzlich sagte mir ein Arbeitskollege, ich solle string.Emptybeim Setzen einer Stringvariablen nicht verwenden, sondern verwenden, nullda dies den Stapel verschmutzt.

Er sagt, tu es nicht

string myString=string.Empty; aber tu es string mystring=null;

Ist es wirklich wichtig? Ich weiß, dass String ein Objekt ist, also macht es irgendwie Sinn.

Ich weiß, ist eine dumme Frage, aber wie ist Ihre Ansicht?


1
Ich bin mir nicht ganz sicher, warum Sie das auch tun würden ... können Sie etwas mehr von dem Code geben, den Sie als Beispiel besprochen haben?
Stusmith

Es gibt keinen Code. Ich habe meinen Kollegen gebeten, sich etwas anzusehen, das ich debuggt habe, und er sagte in der Regel, "nicht string.empty verwenden", setze es auf null, wenn es auf dem Stapel abläuft. Persönlich habe ich immer string.Empty verwendet als die Zeit herauskam, sollte es das Richtige sein, anstatt "".
user712923


Was ich meine ist ... string.Empty, ""und nullalle sind konstante Werte, aber sie sind alle "einfach" genug, dass ich nicht verstehen kann, warum Sie einer Variablen einen zuweisen würden. Wenn Sie eine outVariable erfassen müssen, verwenden Sie sie einfach string myString;.
Stusmith

8
Heutzutage sind Argumente zu solchen Themen, die sich nicht auf Lesbarkeit und Semantik konzentrieren und sich auf absurde Mikrooptimierungen konzentrieren, bestenfalls schwach. Verwenden Sie, was auch immer das Richtige für Ihren gegebenen Kontext bedeutet. (z. B. Wenn Sie wissen, dass jemand keinen zweiten Vornamen hat, verwenden Sie String.Empty; wenn Sie nicht wissen, ob jemand einen zweiten Vornamen hat, den Sie verwenden null). Wenn Sie die richtige Bedeutung haben, schreiben Sie den Code auf eine Weise, die eindeutig korrekt und leicht zu pflegen ist.
Jason

Antworten:


108

nullund Emptysind sehr unterschiedlich, und ich schlage nicht vor, willkürlich zwischen ihnen zu wechseln. Aber keiner hat zusätzliche "Kosten", da Emptyes sich um eine einzelne feste Referenz handelt (Sie können sie beliebig oft verwenden).

Es gibt keine "Verschmutzung" auf dem Stapel, die durch ein ldsfld verursacht wird - diese Sorge ist ... verrückt. Das Laden von a nullist wohl geringfügig billiger, kann jedoch zu Nullreferenzausnahmen führen, wenn Sie den Wert nicht sorgfältig überprüfen.

Persönlich verwende ich keine ... Wenn ich eine leere Zeichenfolge möchte, verwende ich ""- einfach und offensichtlich. Internierung bedeutet, dass dies auch keinen Aufwand pro Nutzung verursacht.


Auf IL-Ebene beträgt der Unterschied zwischen "" und "leer" nur "ldstr" und "ldsfld" - beide geben jedoch dieselbe interne Referenz für einzelne Zeichenfolgen an. Darüber hinaus kann die JIT in neueren .NET-Versionen diese direkt abfangen und liefert die leere Zeichenfolgenreferenz, ohne tatsächlich eine statische Feldsuche durchzuführen. Grundsätzlich gibt es außer der Lesbarkeit keinen Grund, sich darum zu kümmern. Ich benutze nur "".


5
@ user712923 Wenn er mit konkreten Bedenken zurückkommt, würde ich sie gerne hören
Marc Gravell

4
@Marc: ASAIK "" erstellt ein Objekt, in dem string.Empty nicht ist. Überprüfen Sie dies und das . Es hat etwas mit String Intern Pool zu tun ....
Jalal Said


1
+1 für die Verwendung ""anstelle eines sechsmal längeren Boilerplate-Codes. Wer hat diesen Unsinn befürwortet?! @Jalal Dass Brad Abrams Posting ernsthaft veraltet ist und wenn der Compiler diese beiden Codes immer noch nicht optimiert, um dasselbe zu tun, dann schade um Microsoft! Aber es ist nicht unsere Aufgabe, ihre Arbeit zu reparieren. Und tatsächlich müssen wir nicht: Im zweiten Link hat Lasse (in den Kommentaren) die Baugruppenausgaben des Vergleichs mit beiden Varianten verglichen: Sie sind identisch.
Konrad Rudolph

1
@Konrad: Ein Beispiel ist, was passiert, wenn konstante Zeichenfolgen verkettet werden: Die Zeichenfolgenklasse verwendet den internen Pool. Wenn Sie also eine neue Zeichenfolge erstellen, überprüft die Klasse, ob sich die Zeichenfolge bereits im Pool befindet, und fügt sie dann dem Pool hinzu, wenn sie nicht hinzugefügt wird. Aus diesem Grund ""wird der gesamte Pool durchsucht, um zu überprüfen, ob er bereits vorhanden ist oder nicht. Auf diese Weise string.Empty;wird der vordefinierte Wert verwendet und die Suche wird nicht mehr ausgeführt. Die Klasse enthüllte auch diese Methoden: string.Intern/IsInternedÜberprüfen Sie dies
Jalal sagte

34

Es verschmutzt den Stapel nicht, es gibt keinen technischen Grund, aber es gibt einen großen Unterschied zwischen dem Setzen einer Variablen auf einen Verweis auf ein Objekt (selbst wenn es sich um eine leere Zeichenfolge handelt) und null. Sie sind nicht dasselbe und sollten auf unterschiedliche Weise verwendet werden.

nullsollte verwendet werden, um das Fehlen von Daten anzuzeigen, string.Empty(oder "") um das Vorhandensein von Daten anzuzeigen, in der Tat etwas leerer Text. Gibt es einen bestimmten Fall, in dem Sie nicht sicher sind, was am besten geeignet ist?

Bearbeiten, Beispiele hinzugefügt:

  • Sie können string.Emptyals Standard-Postfix für den Namen einer Person verwenden (die meisten Personen haben beispielsweise keinen Doktortitel).

  • Sie können nullfür eine Konfigurationsoption verwenden, die nicht in der Konfigurationsdatei angegeben wurde. In diesem Fall wird string.Emptyverwendet, wenn die Konfigurationsoption vorhanden war, der gewünschte konfigurierte Wert jedoch eine leere Zeichenfolge war.


Ich habe nie so gedacht, muss ich zugeben. Wenn Sie mir sagen, was Sie gerade gesagt haben, haben Sie etwas dagegen, mir ein Beispiel zu geben. Ich weiß, dass Ihre Erklärung selbsterklärend ist, aber dennoch ... danke
user712923

2
Nun, der einzige Grund, sich für das eine oder andere zu entscheiden, hängt von dem Ort ab, an dem Sie es verwenden würden. Dh verwenden string.Emptyoder ""wenn Sie eine leere Zeichenfolge verwenden nullmöchten und wenn Sie angeben möchten, dass keine Daten vorhanden sind. Sie können string.Emptyals Standard-Postfix für den Namen einer Person verwenden (die meisten Personen haben beispielsweise keinen Doktortitel) - und nullfür eine Konfigurationsoption, die nicht in der Konfigurationsdatei angegeben wurde. In diesem zweiten Fall string.Emptywürde verwendet, wenn die Konfigurationsoption vorhanden wäre, der gewünschte konfigurierte Wert jedoch eine leere Zeichenfolge wäre.
Kieren Johnstone

@Kieren Johnstone, wenn man keinen Postfix-Namen hat, warum sollte man dann nicht null"kein Postfix" angeben?
OfirD

8

Sie sind anders, als andere bereits geantwortet haben.

static void Main(string[] args)
{
    string s1 = null;
    string s2 = string.Empty;
    string s3 = "";
    Console.WriteLine(s1 == s2);
    Console.WriteLine(s1 == s3);
    Console.WriteLine(s2 == s3);
}

 results:
 false     - since null is different from string.empty
 false     - since null is different from ""
 true      - since "" is same as string.empty

Das Problem beim Verwalten leerer Zeichenfolgen im Vergleich zu Nullzeichenfolgen wird zu einem Problem, wenn Sie es entweder in einer Einfachdatei speichern oder durch Kommunikation übertragen müssen. Daher finde ich es möglicherweise nützlich, wenn andere, die diese Seite besuchen, eine gute Lösung finden dieses besondere Problem.

Zum Speichern von Zeichenfolgen in einer Datei oder in einer Kommunikation:
Möglicherweise möchten Sie die Zeichenfolge in Bytes konvertieren.
Ich empfehle, Ihrer konvertierten Zeichenfolge 2 Segmente von Header-Bytes hinzuzufügen.

Segment 1 - Meta-Informationen, die in 1 Byte gespeichert sind und die Länge des nächsten Segments beschreiben.

Segment 2 - enthält die Länge der zu speichernden Zeichenfolge.

Beispiel:
Zeichenfolge "abcd" - zur Vereinfachung konvertiere ich sie mit dem ASCII-Encoder und erhalte {65,66,67,68}.
Berechnen Sie Segment 2, um 4 zu erhalten. 4 Bytes sind also die Länge der konvertierten Zeichenfolge.
Berechnen Sie Segment 1, um 1 zu erhalten - da nur 1 Byte verwendet wurde, um die Längeninformationen der konvertierten Zeichenfolgeninformationen zu speichern (4, dh wenn es 260 wäre, würde ich 2 erhalten).

Der neue Byte-Streifen lautet jetzt {1,4,65,66,67,68} und kann in einer Datei gespeichert werden.

Der Vorteil in Bezug auf das Thema ist, dass ich, wenn ich eine leere Zeichenfolge zum Speichern hätte, durch Konvertierung ein leeres Array von Bytes in der Länge 0 erhalten würde und nach der Berechnung der Segmente {1,0} erhalten würde, was sein kann gespeichert und später geladen und wieder in eine leere Zeichenfolge interpretiert. Wenn ich andererseits einen Nullwert in meiner Zeichenfolge hätte, hätte ich am Ende nur {0} als mein zu speicherndes Byte-Array und könnte beim Laden wieder auf Null interpretiert werden.

Es gibt weitere Vorteile, z. B. die Größe der zu ladenden oder zu akkumulierenden Größe, wenn Sie mehrere Zeichenfolgen verschieben.

Zurück zum Thema - es wird den Stapel verschmutzen, da die gleichen beschriebenen Prinzipien von jedem System verwendet werden, um Nullen von leeren zu unterscheiden. Also ja, string.Empty benötigt mehr Speicher als null, obwohl ich es nicht tun würde Nennen wir es Verschmutzung. Es ist nur noch 1 Byte.


1

Es wurde zu Tode beantwortet, aber null bedeutet keinen Wert, nicht initialisiert. string.Empty bedeutet "" (eine leere Zeichenfolge), wie in MSDN angegeben.

Der sicherste Weg, um nach einer leeren oder Null-Zeichenfolge zu suchen, ist die Verwendung von string.IsNullOrEmpty.


-2

FWIW, ich fand das Mischen ""und String.Emptyfunktioniert nicht:

var a = "";
alert("a " + (a == "") + ", " + (a==String.Empty));   //Yields "a true, false"

var b = String.Empty;
alert("b " + (b == "") + ", " + (b == String.Empty)); //Yields "b false, true"

Insbesondere wenn Sie $.trimden Wert eines leeren DOM-Eingabefelds abrufen und mit diesem vergleichen String.Empty, erhalten Sie false. Ich bin mir nicht sicher, warum das so ist, aber los geht's. Ich benutze jetzt einfach ""überall für Konsistenz.


1
Ja. Deshalb sollten wir alle die Gewohnheit .Length==0.Compare()
behalten, zu

14
Diese Frage fragt nach c # not js
Cole Johnson
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.