Wozu dient die Eigenschaft string.Empty?

35

Warum wurde die Immobilie string foo = string.Emptyin die BCL aufgenommen? Es scheint ausführlicher und nicht klarer zu sein, als nur eine leere Zeichenfolge zu verwenden ( string foo = "")

Tom Squires
quelle
6
Nitpick: Es ist nicht Teil der Sprache. Es ist Teil der BCL. VB.NET und F # können es sowie jede andere .NET-Sprache verwenden.
Oded
19
Denn sonst könnten Sie keine bösen Dinge tun typeof(string).GetField("Empty").SetValue(null, " ");;)
Mason Wheeler
1
@ MasonWheeler - Die Freuden der Reflexion. Für das wahre Böse brauchen Sie Selbstbeobachtung, oder?
Oded
1
@MasonWheeler, +1. Oh Gott, die Brille, sie tun nichts!]
Machado
1
@MasonWheeler Das ist reines, destilliertes Böses. Ich liebe es. Frage, wenn Sie interessiert sind: Wäre es nicht sicherer (und anständig performant), es als geschrieben zu haben public static string Empty { get { return string.Intern(""); } }?
Jesse C. Slicer

Antworten:

55

Ich kann hier nur annehmen:

string.Emptywurde aus Gründen der Eindeutigkeit definiert. Beim Initialisieren einer Zeichenfolge wird möglicherweise nicht klar, ob dies ""tatsächlich explizit als Initialisierung gedacht war (anstelle von nulloder sagen " "oder nur als Platzhalter beim Testen). Verwendenstring.Empty ist eine eindeutige Antwort auf diese Art von Rätsel.

Es kann auch ein Rückfall auf C sein - eine leere Zeichenfolge in C ist keine leere Zeichenfolge. Es ist ein Zeichen-Array, dessen erstes Zeichen null ist (daher leer), was nicht mit C # identisch ist. Mein Punkt dabei ist, dass Sie in verschiedenen Sprachen eine leere Zeichenfolge auf unterschiedliche Weise darstellen würden (und sie können unterschiedliche Bedeutungen haben) - eine string.Emptysolche Mehrdeutigkeit auszuschließen.

Im Gegensatz zu anderen Aussagen zu mehreren Objekten ist dies kein Problem, da jedes String-Literal beim Kompilieren interniert wird. Dies beinhaltet den Wert von string.Empty- "". Jedes Mal, wenn eines dieser Elemente im Code wiederholt wird, wird das Objekt aus dem internen Pool abgerufen. Dies gilt pro App-Domain .

Oded
quelle
5
+1 für die bisher einzig richtige Antwort.
PSR
Einige Sprachen vielleicht nicht einmal haben eine leere Zeichenfolge wörtlich zu nehmen . Anscheinend hat es Standard Pascal nicht getan.
Dan04
2
"eine leere Zeichenkette in C ist keine leere Zeichenkette" - aber wenn Sie schreiben "", erhalten Sie trotzdem {'\0'}, so dass es keinen Unterschied zwischen einem leeren Zeichenkettenliteral und einem anderen Umweg gibt, wie man es definiert.
Detly
14

Ich bin mir nicht hundertprozentig sicher, wo ich diese Quellen kennengelernt habe, aber einige der Punkte für die Verwendung sind:

  • Jede Zeichenfolge in einer .NET-Assembly ist eindeutig

    string foo = "";
    string bar = "";

    führt zu 2 Zeichenfolgen in der Ausgabe-Assembly, da Zeichenfolgen unveränderlich sind. Mit beiden Referenzstring.Empty reduziert die Baugruppengröße.

  • Eindeutigkeit. Wenn Sie auf string.Emptydie Absicht stoßen , ist klar, dass es sich um eine leere Zeichenfolge handeln soll. Hat foo = ""der Programmierer beim Testen den Inhalt des Strings entfernt und vergessen, ihn wieder hinzuzufügen, oder soll es so sein?
Agent_9191
quelle
1
Es scheint ein seltsames Verhalten zu sein, wenn zwei identische Zeichenfolgen im Gedächtnis bleiben. Wird das tatsächlich getan?
Rig
36
In der Tat ist das Gegenteil der Fall - es heißt String-Internierung (genauer gesagt Internierung von Literalen). Ich bin mir sicher, dass es in Java und Python funktioniert, und ich bin mir ziemlich sicher, dass dies auch in .NET-Sprachen der Fall ist. Dies kann natürlich nur im Rahmen einer einzelnen Übersetzungseinheit geschehen. Wenn der Dynamic Loader diese Daten nicht vereinheitlicht, erhalten Sie möglicherweise eine leere Zeichenfolge pro Programmdatei. Immer noch nicht sonderlich viel.
9
@delnan ist absolut richtig. ""Ich string.Emptybin interniert und es wird nur ein Objekt erstellt.
Oded
11
@Andy - Alle String- Literale sind in .NET interniert. Nicht alle Saiten. Programmatisch erstellte Zeichenfolgen werden standardmäßig nicht interniert. Siehe String.Intern unter MSDN.
Oded
3
@Oded et alia: Eigentlich hat keiner von euch genau recht. Erstens werden Literale innerhalb einer Assembly interniert, jedoch nicht unbedingt über Assemblys hinweg . Zweitens ist es ein Implementierungsdetail, ob die leere Zeichenfolge über Assemblys hinweg interniert ist oder nicht. Einige Versionen der CLR funktionieren und einige nicht. In einer der anderen Antworten finden Sie einen Link zu meinem Artikel über diese Tatsache. siehe es für die Details.
Eric Lippert
2

Für wird kein Objekt erstellt string.Empty. Mit ""wird ein Objekt erstellt, das höchstwahrscheinlich aus dem String-Intern-Pool stammt.

In der Vergangenheit haben Leute Tests durchgeführt und String.Empty kommen etwas schneller heraus, aber es ist eine Mikrooptimierung.

String.Empty ist das:

//The Empty constant holds the empty string value.   
//We need to call the String constructor so that the compiler doesn't mark 
//this as a literal.   
//Marking this as a literal would mean that it doesn't show up as a field 
//which we can access from native.  
public static readonly String Empty = ""; 
Jon Raynor
quelle
2
Also ist dein Punkt ...?
1
Der Punkt ist String.Empty ist im Grunde eine Konstante für "". Finden Sie den Autor von String.cs für eine tiefere Bedeutung. :)
Jon Raynor
0

Es geht um die Optimierung des Speicherverbrauchs und eine Optimierung des Zeichenfolgenvergleichs. Jedes Mal, wenn Sie in Ihrer Anwendung eine leere Zeichenfolge verwenden, weisen Sie ein Zeichenfolgenobjekt mit 0 Zeichen zu. Der Vergleich von Strings kann durch Vergleichen von Referenzen (Zeigern) anstelle von Zeichen für Zeichen erfolgen, was selbst für leere Strings schneller ist.

Wenn Sie in Ihrer Anwendung mehrmals dieselbe Zeichenfolge verwenden, können Sie dieselbe Art von Mechanismus verwenden, indem Sie String.Intern () mit Ihrer Zeichenfolge aufrufen. Wenn Sie jedoch jede Zeichenfolge nur einmal verwenden, benötigen Sie nur mehr Speicher.

Daher ist String.Empty nur eine Sonderfalloptimierung, die sich für die meisten .NET-Anwendungen lohnt. Deshalb wurde es in die BCL integriert.

Für weitere Details zu diesem Thema empfehle ich dringend, Eric Lipperts Blog-Post zu lesen .

Sie sollten sich auch diese Dokumentation ansehen, auf die in seinem Blogeintrag verwiesen wird.

rold2007
quelle
4
Antworten, die nur mit Links beantwortet werden, sind keine guten Antworten. Sollte Eric jemals sein Blog umorganisieren, wird diese Antwort unbrauchbar. Bitte fassen Sie den Beitrag hier zusammen, damit wir alle Informationen zur Hand haben.
ChrisF
7
@ ChrisF: Ich kann das Blog nie neu organisieren. Das wäre eine bahnbrechende Veränderung, und Sie wissen, wie ich mit diesen umgehe.
Eric Lippert
1
@EricLippert - Mir ist klar, dass Sie das niemals tun würden. Link-only-Antworten sind jedoch keine guten Antworten, und wir müssen die Leute ermutigen, dies zu realisieren.
ChrisF
3
@EricLippert Es geht nicht nur um vergängliche Links. Es geht hier auch um Höflichkeit gegenüber den Lesern. Die Antwort sollte mindestens so viel Inhalt enthalten, dass sich die Leser eine Meinung darüber bilden können, ob sie dem Link folgen sollen. Und die Antwort sollte auch in einer Offline-Kopie von SE Sinn machen.
Gilles 'SO- hör auf böse zu sein'