Was ist der Unterschied zwischen String.Empty und „“ (leere Zeichenkette)?
-
02-07-2019 - |
Frage
In .NET, was ist der Unterschied zwischen String.Empty
und ""
, und sie ist austauschbar, oder gibt es einige zugrunde liegende Referenz oder Lokalisierung Fragen rund um Gleichheit, die sicherstellen, String.Empty
sind kein Problem?
Lösung
In .NET vor Version 2.0, erstellt ""
ein Objekt während string.Empty
kein Objekt erstellt ref , die string.Empty
effizienter macht.
In der Version 2.0 und höher von .NET, alle Vorkommen von ""
auf die gleiche Zeichenfolge beziehen wörtliche, die ""
bedeutet entsprechen .Empty
, aber immer noch nicht so schnell wie .Length == 0
.
.Length == 0
ist die schnellste Option, aber .Empty
macht für etwas saubereren Code.
Sehen Sie die .NET-Spezifikation für weitere Informationen .
Andere Tipps
Was ist der Unterschied zwischen String.Empty und „“, und sie sind austauschbare
string.Empty
ist ein Nur-Lese-Feld während ""
ist eine Kompilierung konstant. Orte, an denen sie sich anders verhalten, sind:
Standard-Parameterwert in C # 4.0 oder höher
void SomeMethod(int ID, string value = string.Empty)
// Error: Default parameter value for 'value' must be a compile-time constant
{
//... implementation
}
Case Ausdruck in switch-Anweisung
string str = "";
switch(str)
{
case string.Empty: // Error: A constant value is expected.
break;
case "":
break;
}
Attribut Argumente
[Example(String.Empty)]
// Error: An attribute argument must be a constant expression, typeof expression
// or array creation expression of an attribute parameter type
Die bisherigen Antworten für .NET 1.1 korrekt waren (Blick auf das Datum des Posts sie verbunden: 2003). Ab .NET 2.0 und höher, gibt es im wesentlichen keinen Unterschied. Der JIT wird bis Bezugnahme auf das gleiche Objekt auf dem Heap sowieso beenden.
Nach der C # Spezifikation, Abschnitt 2.4.4.5: http://msdn.microsoft.com/en-us/ library / aa691090 (VS.71) aspx
Jeder Stringliteral führt nicht notwendigerweise in einer neuen String-Instanz. Wenn zwei oder mehr Zeichenketten, die äquivalent sind, entsprechend der Zeichenfolge Gleichheitsoperator (Abschnitt 7.9.7) in der gleichen Anordnung erscheinen, beziehen sich diese Stringliterale auf den gleichen String-Instanz.
Jemand sogar erwähnt dies in den Kommentaren von Brad Abrams Post
Zusammenfassend das praktische Ergebnis von „“ vs. String.Empty ist gleich Null. Der JIT wird es heraus am Ende heraus.
Ich habe persönlich festgestellt, dass der JIT als ich viel schlauer ist und ich versuche so nicht zu klug zu bekommen mit Mikro-Compiler-Optimierungen wie die. Der JIT wird sich entfalten für () Schleifen, Entfernen redundanten Code, Inline Methoden usw. besser und zu geeigneteren Zeiten als entweder I oder das C # Compiler könnte je Hand antizipieren. Lassen Sie die JIT seine Aufgabe:)
String.Empty
ist ein Read-only Feld während ""
ist ein const . Dies bedeutet, dass Sie nicht String.Empty
in einer switch-Anweisung verwenden können, weil es keine Konstante ist.
Ein weiterer Unterschied besteht darin, dass String.Empty größer CIL-Code erzeugt. Während der Code für die Referenzierung „“ und String.Empty die gleiche Länge ist, wird der Compiler nicht String-Verkettung (siehe Eric Lippert Blog-Post ) für String.Empty Argumente. Folgende äquivalente Funktionen
string foo()
{
return "foo" + "";
}
string bar()
{
return "bar" + string.Empty;
}
Dieses IL erzeugen
.method private hidebysig instance string foo() cil managed
{
.maxstack 8
L_0000: ldstr "foo"
L_0005: ret
}
.method private hidebysig instance string bar() cil managed
{
.maxstack 8
L_0000: ldstr "bar"
L_0005: ldsfld string [mscorlib]System.String::Empty
L_000a: call string [mscorlib]System.String::Concat(string, string)
L_000f: ret
}
Die oben genannten Antworten sind technisch korrekt, aber was Sie wirklich nutzen wollen können, für beste Lesbarkeit des Codes und geringste Chance einer Ausnahme ist String.IsNullOrEmpty (s)
Ich neige dazu, String.Empty
zu verwenden, anstatt ""
für eine einfache, aber nicht offensichtlichen Grund:
""
""
und sind nicht die gleichen, die erste hat tatsächlich 16 Breite von Null-Zeichen darin. Offensichtlich kein zuständiger Entwickler wird setzen und eine Breite von Null-Zeichen in ihren Code, aber wenn sie dort bekommen haben, kann es ein Alptraum in Sachen Wartung sein.
Weitere Informationen:
-
Ich benutzte U + FEFF in dieser Beispiel.
-
Nicht sicher, ob SO diese Zeichen essen wird, aber versuchen Sie es selbst mit einem der vielen Null-Breite Zeichen
-
Ich kam nur über dies dank https://codegolf.stackexchange.com/
Verwenden String.Empty
statt ""
.
Das ist mehr für die Geschwindigkeit als Speichernutzung, aber es ist ein nützlicher Tipp. Das
""
ist eine wörtliche wird, um eine wörtliche handeln: auf dem ersten Gebrauch ist erstellt und für die folgende verwendet seine Referenz zurückgegeben wird. Nur eine Instanz""
wird, egal in einem Speicher gespeichert werden, wie oft wir benutze es! Ich sehe keine Speicher Strafen hier. Das Problem ist, dass Jedesmal, wenn der""
verwendet wird, wird eine Vergleichsschleife, wenn das überprüft ausgeführt""
ist bereits im internen Pool. Auf der anderen Seite,String.Empty
ist ein Verweis auf eine""
in der .NET Framework Speicherzone gespeichert.String.Empty
zeigt auf gleiche Speicheradresse für VB.NET und C # Anwendungen. Warum also für eine Referenz suchen jedes Mal, wenn Sie""
brauchen wenn Sie diesen Verweis inString.Empty
haben?
Referenz: String.Empty
vs ""
String.Empty kein Objekt erstellen, während „“ der Fall ist. Der Unterschied, wie rel="noreferrer">, ist trivial, jedoch.
Es ist einfach keine Rolle!
Einige Vergangenheit die Diskussion über diese:
http://www.codinghorror.com/blog/archives/000185.html
http://blogs.msdn.com/brada/ Archiv / 2003/04/22 / 49997.aspx
http://blogs.msdn.com/brada/ Archiv / 2003/04/27 / 50014.aspx
Alle Instanzen von „“ ist der gleiche, internierte Stringliteral (oder sie sollen). Sie wird also nicht wirklich ein neues Objekt auf dem Heap wirft jedes Mal, Sie „“, sondern nur einen Verweis auf das gleiche, internierte Objekt erstellen. Having said that, ich ziehe string.Empty. Ich denke, es Code besser lesbar macht.
string mystring = "";
ldstr ""
ldstr
schiebt ein neues Objekt Verweis auf eine Stringliteral in den Metadaten gespeichert.
string mystring = String.Empty;
ldsfld string [mscorlib]System.String::Empty
ldsfld
drückt den Wert eines statischen Feldes auf den Auswertungsstapel
Ich neige dazu, String.Empty
zu verwenden, anstatt ""
weil IMHO ist es klarer und VB-ish.
auf diesem Von einer Entity Framework Sicht: EF-Versionen 6.1.3 erscheinen String.Empty und „“ unterschiedlich zu behandeln, wenn die Validierung.
string.Empty wird als Nullwert für Validierungszwecke behandelt und einen Überprüfungsfehler auslösen, wenn es auf einem Required (zugeschrieben) Feld verwendet wird; wo als „“ wird die Überprüfung bestanden und nicht den Fehler werfen.
Dieses Problem kann in EF 7+ gelöst werden. Referenz: - https://github.com/aspnet/EntityFramework/issues/2610 ).
Edit:. [Erforderlich (AllowEmptyStrings = true)] wird dieses Problem beheben, so dass string.Empty zu validieren
Da String.Empty keine Compile-Zeit konstant ist, dass Sie es nicht als Standardwert in Funktionsdefinition verwenden können.
public void test(int i=0,string s="")
{
// Function Body
}
Eric Lippert schrieb (17, Juni 2013):
"der erste Algorithmus I der Optimierer in der C # Compiler bearbeitet jemals war die Zeichenfolge Verkettungen Griffe Leider schaffe ich es nicht zu. Port diese Optimierungen an der Roslyn Code-Basis, bevor ich ging;! jemand das wird hoffentlich bekommen "
Hier sind einige Roslyn x64 Ergebnisse ab Januar 2019. Trotz der Konsens Bemerkungen der anderen Antworten auf dieser Seite, es mir scheint, dass die aktuelle x64 JIT all diesen Fällen ist die Behandlung identisch, wenn alles gesagt und getan ist.
Hinweis insbesondere jedoch, dass nur eines dieser Beispiele endet tatsächlich bis String.Concat
nennen, und ich vermute, dass das aus unerfindlichen Gründen Korrektheit ist (im Gegensatz zu einer Optimierung Aufsicht gegenüber). Die anderen Unterschiede scheinen schwerer zu erklären.
default (String) + {default (String), "", String.Empty}
static String s00() => default(String) + default(String);
mov rax,[String::Empty]
mov rax,qword ptr [rax]
add rsp,28h
ret
static String s01() => default(String) + "";
mov rax,[String::Empty]
mov rax,qword ptr [rax]
add rsp,28h
ret
static String s02() => default(String) + String.Empty;
mov rax,[String::Empty]
mov rax,qword ptr [rax]
mov rdx,rax
test rdx,rdx
jne _L
mov rdx,rax
_L: mov rax,rdx
add rsp,28h
ret
"" + {default (String), "", String.Empty}
static String s03() => "" + default(String);
mov rax,[String::Empty]
mov rax,qword ptr [rax]
add rsp,28h
ret
static String s04() => "" + "";
mov rax,[String::Empty]
mov rax,qword ptr [rax]
add rsp,28h
ret
static String s05() => "" + String.Empty;
mov rax,[String::Empty]
mov rax,qword ptr [rax]
mov rdx,rax
test rdx,rdx
jne _L
mov rdx,rax
_L: mov rax,rdx
add rsp,28h
ret
String.Empty + {default (String), "", String.Empty}
static String s06() => String.Empty + default(String);
mov rax,[String::Empty]
mov rax,qword ptr [rax]
mov rdx,rax
test rdx,rdx
jne _L
mov rdx,rax
_L: mov rax,rdx
add rsp,28h
ret
static String s07() => String.Empty + "";
mov rax,[String::Empty]
mov rax,qword ptr [rax]
mov rdx,rax
test rdx,rdx
jne _L
mov rdx,rax
_L: mov rax,rdx
add rsp,28h
ret
static String s08() => String.Empty + String.Empty;
mov rcx,[String::Empty]
mov rcx,qword ptr [rcx]
mov qword ptr [rsp+20h],rcx
mov rcx,qword ptr [rsp+20h]
mov rdx,qword ptr [rsp+20h]
call F330CF60 ; <-- String.Concat
nop
add rsp,28h
ret
Testdetails
Microsoft (R) Visual C# Compiler version 2.10.0.0 (b9fb1610)
AMD64 Release
[MethodImpl(MethodImplOptions.NoInlining)]
'SuppressJitOptimization' = false
Wenn Sie visuell sind durch Code scannen „“ erscheint die Art und Weise Strings koloriert sind koloriert. string.Empty sieht aus wie ein normaler Klasse-Memberzugriff. Während eines kurzen Blicks, seine leichter zu erkennen „“ oder die Bedeutung erahnen.
Spot the Strings (Stack-Überlauf Einfärben ist nicht gerade helfen, aber in VS ist dies offensichtliches):
var i = 30;
var f = Math.Pi;
var s = "";
var d = 22.2m;
var t = "I am some text";
var e = string.Empty;
Jeder hier gab einige gute theoretische Klärung. Ich hatte einen ähnlichen Zweifel. Also habe ich versucht, eine grundlegende Codierung darauf. Und ich fand einen Unterschied. Hier ist der Unterschied.
string str=null;
Console.WriteLine(str.Length); // Exception(NullRefernceException) for pointing to null reference.
string str = string.Empty;
Console.WriteLine(str.Length); // 0
So ist es „Null“ scheint bedeutet absolut nichtig & „String.Empty“ bedeutet Es enthält eine Art von Wert, aber es ist leer.