string.Empty vs null. Którego używasz?

84

Niedawno kolega z pracy powiedział mi, żebym nie używał string.Emptyprzy ustawianiu zmiennej łańcuchowej, ale używał nulljej, ponieważ zanieczyszcza stos?

Mówi, że nie rób

string myString=string.Empty; ale zrób string mystring=null;

Czy to naprawdę ma znaczenie? Wiem, że ciąg jest obiektem, więc ma sens.

Wiem, że to głupie pytanie, ale co o tym sądzisz?

user712923
źródło
1
Nie jestem do końca pewien, dlaczego też byś to zrobił ... czy możesz podać trochę więcej kodu, o którym rozmawiałeś, jako przykład?
stusmith
nie ma kodu. Poprosiłem mojego kolegę, aby spojrzał na coś, co debuguję, a on powiedział jako ogólną zasadę "nie używaj string.empty" ustaw go na null, gdy idzie na stos. Osobiście zawsze używałem string.Empty ponieważ czas się ukazał miał być raczej właściwą rzeczą do użycia niż "".
user712923
Chodzi mi o to ... string.Empty, ""i nullwszystkie są wartościami stałymi, ale wszystkie są na tyle „proste”, że nie rozumiem, dlaczego przypisujesz je do zmiennej. Jeśli chcesz przechwycić outzmienną, dlaczego po prostu nie użyć string myString;?
stusmith
8
Obecnie argumenty na tematy takie jak ten, które nie koncentrują się na czytelności i semantyce, a koncentrują się na absurdalnych mikrooptymalizacjach, są w najlepszym przypadku słabe. Użyj tego, co oznacza właściwą dla danego kontekstu. (np. jeśli wiesz, że ktoś nie ma drugiego imienia, użyj String.Empty; jeśli nie wiesz, czy ktoś ma drugie imię, którego używasz null). Następnie, gdy masz już odpowiednie znaczenie, napisz kod w sposób, który jest wyraźnie poprawny i łatwy w utrzymaniu.
jason,

Odpowiedzi:

110

nulli Emptysą bardzo różne i nie sugeruję przypadkowego przełączania się między nimi. Ale nie ma żadnego dodatkowego „kosztu”, ponieważ Emptyjest to jedno stałe odniesienie (możesz go użyć dowolną liczbę razy).

Na stosie nie ma „zanieczyszczeń” spowodowanych przez ldsfld - ta obawa jest… szalona. Załadowanie a nulljest prawdopodobnie nieznacznie tańsze, ale może spowodować wyjątki zerowych odwołań, jeśli nie jesteś ostrożny podczas sprawdzania wartości.

Osobiście nie używam żadnego ... Jeśli chcę mieć pusty ciąg, używam ""- proste i oczywiste. Internowanie oznacza również, że nie ma narzutu na użycie.


Na poziomie IL różnica między "" a Empty jest po prostu ldstr vs ldsfld - ale oba podają to samo pojedyncze wewnętrzne odwołanie do łańcucha. Co więcej, w nowszych wersjach .NET JIT przechwytuje je bezpośrednio, uzyskując odwołanie do pustego ciągu bez faktycznego wyszukiwania pól statycznych. Zasadniczo nie ma żadnego powodu, by się tym przejmować, z wyjątkiem czytelności. Po prostu używam „”.

Marc Gravell
źródło
5
@ user712923, jeśli wróci z konkretnymi obawami, z przyjemnością je wysłucham
Marc Gravell
4
@Marc: ASAIK "" tworzy obiekt, w którym string.Empty nie jest .. sprawdź to i to . Ma to coś wspólnego z basenem stażystów ...
powiedział Jalal
7
@Hemal: String.IsNullOrEmpty ()
Vinko Vrsalovic
1
+1 za użycie ""zamiast sześciokrotnie dłuższego standardowego kodu. Kto popierał ten nonsens ?! @Jalal To, że publikacja Brada Abramsa jest poważnie przestarzała i jeśli kompilator nadal nie optymalizuje tych dwóch kodów, aby zrobić to samo, szkoda Microsoft! Ale nie naszym zadaniem jest naprawianie ich pracy. W rzeczywistości nie musimy: W drugim łączu Lasse (w komentarzach) porównał dane wyjściowe zespołu podczas porównywania z każdym wariantem: są one identyczne.
Konrad Rudolph
1
@Konrad: Jednym z przykładów jest to, co dzieje się podczas łączenia stałych ciągów: klasa ciągów używa puli stażystów, więc kiedy tworzysz nowy ciąg, klasa sprawdza, czy ciąg jest już w puli, a następnie, jeśli nie dodaje go do puli. Z tego powodu, gdy ""będzie przeszukiwać całą pulę, aby sprawdzić, czy już tam jest, czy nie, i tak jest, gdy string.Empty;użyje tej predefiniowanej wartości, a wyszukiwanie już nie będzie istniało . klasa również ujawniła te metody: string.Intern/IsInternedsprawdź to
Jalal powiedział
34

Nie `` zanieczyszcza stosu '', nie ma żadnego technicznego powodu, ale istnieje duża różnica między ustawieniem zmiennej na odniesienie do obiektu (nawet jeśli jest to pusty ciąg) a null. Nie są tym samym i powinny być używane na różne sposoby.

nullpowinien być używany do wskazania braku danych, string.Empty(lub "") do wskazania obecności danych, w rzeczywistości jakiegoś pustego tekstu. Czy istnieje konkretny przypadek, w którym nie masz pewności, co jest najbardziej odpowiednie?

Edycja, dodane przykłady:

  • Możesz użyć string.Emptyjako domyślnego przyrostka dla nazwiska osoby (większość ludzi na przykład nie ma doktoratu)

  • Możesz użyć nulldla opcji konfiguracji, która nie została określona w pliku konfiguracyjnym. W tym przypadku string.Emptyzostanie użyty, jeśli opcja config była obecna, ale żądana skonfigurowana wartość byłaby pustym ciągiem.

Kieren Johnstone
źródło
Muszę przyznać, że nigdy nie myślałem w ten sposób. Biorąc pod uwagę to, co właśnie powiedziałeś, czy możesz podać mi przykład. Wiem, że twoje wyjaśnienie jest oczywiste, ale nadal ... dzięki
user712923
2
Cóż, jedynym powodem wyboru jednego lub drugiego jest miejsce, w którym go użyjesz. Tzn. Użyj string.Emptylub, ""gdy chcesz użyć pustego ciągu i nullgdy chcesz wskazać, że nie ma danych. Możesz użyć string.Emptyjako domyślnego przyrostka dla nazwiska osoby (większość ludzi nie ma na przykład doktoratu) - i nulldla opcji konfiguracyjnej, która nie została określona w pliku konfiguracyjnym. W drugim przypadku string.Emptyzostanie użyty, jeśli opcja config była obecna, ale żądana skonfigurowana wartość była pustym ciągiem.
Kieren Johnstone,
@Kieren Johnstone, jeśli ktoś nie ma nazwy postfiksowej, dlaczego nie użyłby nullokreślenia „no postfix”?
OfirD
8

Są różni, jak inni już odpowiedzieli.

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

Problem z zarządzaniem ciągami pustymi w porównaniu z ciągami zerowymi staje się problemem, gdy trzeba zachować go w płaskim pliku lub przesłać go za pomocą komunikacji, więc uważam, że może być przydatne dla innych, którzy odwiedzają tę stronę, aby dać dobre rozwiązanie ten konkretny problem.

W celu zapisania łańcuchów do pliku lub komunikacji:
prawdopodobnie będziesz chciał przekonwertować łańcuch na bajty.
dobrą praktyką, którą polecam, jest dodanie 2 segmentów bajtów nagłówka do przekonwertowanego ciągu.

segment 1 - metainformacja, która jest przechowywana w 1 bajcie i opisuje długość następnego segmentu.

segment 2 - zawiera długość zapisywanego ciągu.

przykład:
string "abcd" - dla uproszczenia przekonwertuję go za pomocą kodera ASCII i otrzymam {65,66,67,68}.
Oblicz segment 2 da 4 - więc 4 bajty to długość przekonwertowanego ciągu.
obliczyć segment 1 daje 1 - ponieważ tylko 1 bajt został użyty do przechowywania informacji o długości przekonwertowanej informacji ciągu (czyli 4, tj. gdyby było to 260, dostałbym 2)

Nowy pasek bajtów będzie miał teraz wartość {1,4,65,66,67,68}, który można zapisać do pliku.

Zaletą w odniesieniu do tematu jest to, że gdybym miał pusty ciąg do zapisania, otrzymałbym z konwersji pustą tablicę bajtów o długości 0 i po obliczeniu segmentów otrzymam {1,0}, które może być zapisane, a później załadowane i zinterpretowane z powrotem w pusty łańcuch. Z drugiej strony, gdybym miał wartość null w swoim ciągu, miałbym tylko {0} jako moją tablicę bajtów do zapisania, a po załadowaniu można zinterpretować z powrotem do null.

Istnieje więcej korzyści, takich jak wiedza o rozmiarze do załadowania lub zgromadzenia, jeśli zerwasz wiele ciągów.

Wracając do tematu - to… cóż, w pewnym sensie zanieczyści stos, ponieważ te same opisane zasady są używane przez każdy system do rozróżniania wartości null od pustych .. więc tak, string.Empty zajmuje więcej pamięci niż null, chociaż nie zrobiłbym tego nazwij to zanieczyszczeniem ... to tylko 1 bajt więcej.

GY
źródło
1

Odpowiedziano mu na śmierć, ale zero oznacza brak wartości, nie zainicjowano. string.Empty oznacza „” (pusty ciąg), tak jak podano w MSDN.

Najbezpieczniejszym sposobem sprawdzenia pustego lub zerowego ciągu jest użycie string.IsNullOrEmpty.

Carlos A Merighe
źródło
-2

FWIW, znalazłem to miksowanie ""i String.Emptynie działa:

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"

W szczególności, jeśli użyjesz $.trimdo pobrania wartości pustego pola wejściowego DOM, a następnie porównaj ją z String.Empty, otrzymasz false. Nie wiem, dlaczego tak jest, ale proszę bardzo. Teraz po prostu używam ""wszędzie dla spójności.

user1072817
źródło
1
Tak. Dlatego wszyscy powinniśmy mieć zwyczaj sprawdzania .Length==0lub używania.Compare()
zanlok
14
To pytanie dotyczy c # not js
Cole Johnson