Jaka jest różnica między String.Empty i „” (pusty ciąg)?

głosy
244

W .NET, jaka jest różnica między String.Emptya i są one wymienne, czy istnieją jakieś odniesienia lub lokalizacyjne podstawowe kwestie związane z równością, która String.Emptyzapewni nie są problemem?

Utwórz 30/09/2008 o 02:59
źródło użytkownik
W innych językach...                            


17 odpowiedzi

głosy
244

W .NET wcześniejszej do wersji 2.0, ""tworzy obiekt natomiast string.Emptystwarza żadnego obiektu ref , co sprawia, że string.Emptybardziej efektywne.

W wersji 2.0 i nowszej .NET, wszystkie wystąpienia ""odnoszą się do tego samego łańcucha dosłownym, czyli ""jest równoważne .Empty, ale nie tak szybko, jak .Length == 0.

.Length == 0to najszybsza opcja, ale .Emptysprawia, że nieco czystsze kodu.

Zobacz specyfikację .NET, aby uzyskać więcej informacji .

Odpowiedział 30/09/2008 o 03:02
źródło użytkownik

głosy
159

Jaka jest różnica między String.Empty i „”, i są one wymienne

string.EmptyJest to pole tylko do odczytu, natomiast ""jest kompilacji stałą czasową. Miejsca, w których są one zachowują się inaczej:

Domyślna wartość parametru w C # 4.0 lub wyższy

void SomeMethod(int ID, string value = string.Empty)
// Error: Default parameter value for 'value' must be a compile-time constant
{
    //... implementation
}

Wyrażenie case w instrukcji switch

string str = "";
switch(str)
{
    case string.Empty: // Error: A constant value is expected. 
        break;

    case "":
        break;

}

Atrybut argumenty

[Example(String.Empty)]
// Error: An attribute argument must be a constant expression, typeof expression 
//        or array creation expression of an attribute parameter type
Odpowiedział 04/12/2012 o 13:39
źródło użytkownik

głosy
36

Dotychczasowe odpowiedzi były prawidłowe dla .NET 1.1 (spójrz na dzień postu one powiązane: 2003). Począwszy od .NET 2.0 i później, nie ma w zasadzie żadnej różnicy. JIT skończy się odwołuje się do tego samego obiektu na stercie byle jak.

Według specyfikacji C # sekcja 2.4.4.5: http://msdn.microsoft.com/en-us/library/aa691090(VS.71).aspx

Każdy łańcuch dosłowny nie koniecznie doprowadzić do nowej instancji strun. Gdy dwa lub więcej literałami łańcuch, które są równoważne zgodnie z operatorem równości łańcuch (rozdział 7.9.7) się w tym samym zespole, te literałami łańcuch odnoszą się do tego samego przykładu strun.

Ktoś nawet wspomina o tym w komentarzach postu Brad Abrama

Podsumowując, praktycznym skutkiem „” vs. String.Empty jest zerowa. JIT będzie zrozumieć to w końcu.

Znalazłem, osobiście, że JIT jest sposób mądrzejszy ode mnie i tak staram się nie dostać zbyt mądry z mikro-optymalizacje kompilatora w tym stylu. JIT będzie rozłożyć na () pętli, usunąć nadmiarowy kod, metody inline, etc lepiej iw bardziej odpowiednich porach niż jednej I lub C # kompilator mógł kiedykolwiek przewidzieć przed ręką. Niech JIT zrobić swoją pracę :)

Odpowiedział 30/09/2008 o 03:19
źródło użytkownik

głosy
33

String.Emptyjest tylko do odczytu , podczas gdy pole ""jest const . Oznacza to, że nie można używać String.Emptyw instrukcji switch, ponieważ nie jest stała.

Odpowiedział 01/10/2008 o 04:18
źródło użytkownik

głosy
16

Inną różnicą jest to, że String.Empty generuje większy kod CIL. Natomiast kod na przedstawieniu „” i String.Empty jest tej samej długości, kompilator nie zoptymalizować konkatenacji ciągów (patrz Eric Lippert na blogu ) dla argumentów String.Empty. Następujące równoważne funkcje

string foo()
{
    return "foo" + "";
}
string bar()
{
    return "bar" + string.Empty;
}

wygenerowania tego IL

.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 
}
Odpowiedział 30/06/2013 o 03:07
źródło użytkownik

głosy
13

Powyższe odpowiedzi są poprawne technicznie, ale co może naprawdę chcesz używać, za najlepszą czytelność kodu i najmniejszej szansy wyjątek jest string.IsNullOrEmpty (s)

Odpowiedział 30/09/2008 o 05:06
źródło użytkownik

głosy
8

Użyj String.Emptyzamiast "".

To więcej niż na szybkości zużycia pamięci, ale jest przydatna wskazówka. ""Jest dosłownym tak będzie działać jako dosłowna: od pierwszego użycia i jest on stworzony dla następujących zastosowań jego odniesienia jest zwracana. Tylko jedna instancja ""zostanie zapisana w pamięci bez względu na to ile razy go używać! Nie widzę tu żadnych kar pamięci. Problemem jest to, że za każdym razem gdy ""jest stosowana, porównując pętla jest wykonywana w celu sprawdzenia, czy ""jest już w intern basenie. Z drugiej strony, String.Empty jest to odniesienie do ""przechowywany w strefie pamięci .NET Framework . String.Emptyjest skierowany do tego samego adresu pamięci do VB.NET i C # aplikacji. Dlaczego więc szukać odniesienia za każdym razem trzeba "" , kiedy trzeba, że odniesienie w String.Empty?

Numer referencyjny: String.Emptyvs""

Odpowiedział 11/02/2016 o 09:20
źródło użytkownik

głosy
6

Wszystkie przypadki „” są takie same, internowany Łańcuch znaków (lub powinny być). Tak naprawdę nie będą rzucać nowego obiektu na stercie za każdym razem użyć „” ale tylko tworzenie odniesienie do tego samego obiektu, internowany. Mimo, że wolę string.Empty. Myślę, że to sprawia, że ​​kod jest bardziej czytelny.

Odpowiedział 30/09/2008 o 03:08
źródło użytkownik

głosy
6

String.Empty nie tworzy obiekt, natomiast „” robi. Różnica, jak wskazano tutaj , jest trywialne, jednak.

Odpowiedział 30/09/2008 o 03:02
źródło użytkownik

głosy
5

I mają tendencję do używania String.Emptyzamiast ""na jeden prosty, ale nie oczywistego powodu: ""a ""to nie to samo, pierwszy faktycznie ma 16 znaków zerowej szerokości w nim. Oczywiście nie właściwy deweloper zamierza umieścić i zero szerokości znaków w kodzie, ale jeżeli się tam dostać, to może być koszmar utrzymanie.

Uwagi:

  • Kiedyś U + FEFF w tym przykładzie.

  • Nie wiesz, jeśli tak się dzieje, aby jeść te znaki, ale spróbuj sam z jednym z wielu znaków o zerowej szerokości

  • Przyszedłem tylko po to dzięki https://codegolf.stackexchange.com/

Odpowiedział 25/11/2015 o 11:42
źródło użytkownik

Odpowiedział 30/09/2008 o 03:05
źródło użytkownik

głosy
4
string mystring = "";
ldstr ""

ldstr popycha nowe odniesienie do obiektu ciąg dosłowne przechowywanej w metadanych.

string mystring = String.Empty;
ldsfld string [mscorlib]System.String::Empty

ldsfld popycha wartość pola statycznego na stosie oceny

I mają tendencję do używania String.Emptyzamiast ""bo IMHO to jaśniejsze i mniej VB-owski.

Odpowiedział 17/04/2015 o 16:34
źródło użytkownik

głosy
2

Jadąc na to z punktu widzenia Entity Framework: EF wersje 6.1.3 wydaje się traktować String.Empty i „” inaczej podczas walidacji.

string.Empty jest traktowana jako wartość null dla celów walidacji i rzuci błąd sprawdzania poprawności, jeśli jest używany na potrzeby (przypisane) dziedzinie; gdzie jako „” przejdzie walidację i nie rzucać się błąd.

Problem ten może być rozwiązany w EF 7+. Odniesienie: - https://github.com/aspnet/EntityFramework/issues/2610 ).

Edit: [Wymagane (AllowEmptyStrings = true)] będzie rozwiązać ten problem, pozwalając string.Empty aby potwierdzić.

Odpowiedział 09/03/2017 o 11:59
źródło użytkownik

głosy
1

Eric Lippert napisał (17 czerwca 2013):
„Pierwszy algorytm kiedykolwiek pracował w C # kompilator był optymalizator, który obsługuje powiązań, ciągów. Niestety nie udało mi się do portu te optymalizacje w kodzie Roslyn przed wyjazdem; mam nadzieję, że ktoś będzie dostać się do tego! "

Oto kilka Roslyn x64 wyniki od stycznia 2019 roku, pomimo uwag konsensusu innych odpowiedzi na tej stronie, to nie wydaje mi się, że obecny 64 JIT jest traktowanie wszystkich tych przypadkach identycznie, kiedy wszystko jest powiedziane i zrobione.

Zwrócić szczególną uwagę na to jednak, że tylko jeden z tych przykładów faktycznie kończy się wywołaniem String.Concati zgaduję, że to dla niejasnych powodów poprawności (w przeciwieństwie do nadzoru Optimization). Pozostałe różnice wydają się trudniejsze do wyjaśnienia.


domyślne (String) + ...

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

"" + ...

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 + ...

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


dane testowe

Microsoft (R) Visual C# Compiler version 2.10.0.0 (b9fb1610)
AMD64 Release
[MethodImpl(MethodImplOptions.NoInlining)]
'SuppressJitOptimization' = false
Odpowiedział 31/01/2019 o 04:42
źródło użytkownik

głosy
1

Od String.Empty nie jest stałą czasu kompilacji nie można używać go jako wartość domyślną w definicji funkcji.

public void test(int i=0,string s="")
    {
      // Function Body
    }
Odpowiedział 14/03/2017 o 07:11
źródło użytkownik

głosy
0

Kiedy wizualnie skanowanie za pomocą kodu „” wydaje pokolorowane sposób ciągi są pokolorowane. string.Empty wygląda jak zwykły klasy państwie dostępu. Podczas szybkiego spojrzenia, jego łatwiejsze do wykrycia „” lub wyczuć sens.

Spot struny (przepełnienie stosu koloryzacja nie jest dokładnie pomaga, ale w VS jest to bardziej oczywiste):

var i = 30;
var f = Math.Pi;
var s = "";
var d = 22.2m;
var t = "I am some text";
var e = string.Empty;
Odpowiedział 07/05/2019 o 16:58
źródło użytkownik

głosy
-4

Wszyscy tu dał kilka dobrych wyjaśnień teoretycznych. Miałem podobny wątpliwości. Spróbowałem więc podstawowe kodowanie na nim. I znalazłem różnicę. Tu jest różnica.

string str=null;
Console.WriteLine(str.Length);  // Exception(NullRefernceException) for pointing to null reference. 


string str = string.Empty;
Console.WriteLine(str.Length);  // 0

Wydaje się więc, „Null” oznacza bezwzględnie nieważna i „String.Empty” Oznacza to, że zawiera jakąś wartość, ale jest pusty.

Odpowiedział 21/01/2016 o 15:57
źródło użytkownik

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more