W języku C # chcę zainicjować wartość ciągu pustym ciągiem.
Jak mam to zrobić? Jaka jest właściwa droga i dlaczego?
string willi = string.Empty;
lub
string willi = String.Empty;
lub
string willi = "";
albo co?
W języku C # chcę zainicjować wartość ciągu pustym ciągiem.
Jak mam to zrobić? Jaka jest właściwa droga i dlaczego?
string willi = string.Empty;
lub
string willi = String.Empty;
lub
string willi = "";
albo co?
Odpowiedzi:
Używaj tego, co Ty i Twój zespół uznacie za najbardziej czytelne.
Inne odpowiedzi sugerują, że za każdym razem tworzony jest nowy ciąg ""
. Nie jest to prawdą - ze względu na internowanie ciągów zostanie on utworzony albo raz na zespół, albo raz na AppDomain (lub ewentualnie raz dla całego procesu - nie jestem pewien z tej strony). Różnica ta jest znikoma - masowo, masowo nieistotna.
Jednak to, co uważasz za bardziej czytelne, to inna sprawa. Jest to subiektywne i będzie się różnić w zależności od osoby - dlatego sugeruję, abyś przekonał się, jak lubi większość ludzi w zespole i wszyscy zachowują spójność. Osobiście uważam, że ""
łatwiej jest czytać.
Argument, że ""
i " "
są łatwo pomylić z siebie naprawdę nie myć się ze mną. O ile nie używasz czcionki proporcjonalnej (a ja nie współpracowałem z żadnymi programistami, którzy to robią), dość łatwo jest odróżnić.
string.Empty
nie jest stała . Oznacza to, że w wielu przypadkach, w których wymagana jest stała czasowa kompilacji, string.Empty
nie jest nawet legalna. Obejmuje to case ""
bloki w switch
instrukcjach, wartości domyślne parametrów opcjonalnych , parametry i właściwości w stosowaniu atrybutów oraz wiele innych sytuacji (pozostawionych czytelnikowi). Biorąc pod uwagę, że string.Empty
jest to niedozwolone w niektórych typowych sytuacjach, lepiej zastosować ""
konwencję -w każdym innym miejscu.
Naprawdę nie ma różnicy z punktu widzenia wydajności i generowanego kodu. W testach wydajności poruszali się tam iz powrotem, między którymi jedno było szybsze w porównaniu do drugiego i tylko o milisekundy.
Patrząc na kod za kulisami, naprawdę nie widzisz żadnej różnicy. Jedyną różnicą jest IL, która string.Empty
korzysta z opcodu ldsfld
i ""
używa opcodu ldstr
, ale string.Empty
dzieje się tak tylko dlatego, że jest statyczna i obie instrukcje robią to samo. Jeśli spojrzysz na zespół, który jest produkowany, jest dokładnie taki sam.
private void Test1()
{
string test1 = string.Empty;
string test11 = test1;
}
private void Test2()
{
string test2 = "";
string test22 = test2;
}
.method private hidebysig instance void
Test1() cil managed
{
// Code size 10 (0xa)
.maxstack 1
.locals init ([0] string test1,
[1] string test11)
IL_0000: nop
IL_0001: ldsfld string [mscorlib]System.String::Empty
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: stloc.1
IL_0009: ret
} // end of method Form1::Test1
.method private hidebysig instance void
Test2() cil managed
{
// Code size 10 (0xa)
.maxstack 1
.locals init ([0] string test2,
[1] string test22)
IL_0000: nop
IL_0001: ldstr ""
IL_0006: stloc.0
IL_0007: ldloc.0
IL_0008: stloc.1
IL_0009: ret
} // end of method Form1::Test2
string test1 = string.Empty;
0000003a mov eax,dword ptr ds:[022A102Ch]
0000003f mov dword ptr [ebp-40h],eax
string test11 = test1;
00000042 mov eax,dword ptr [ebp-40h]
00000045 mov dword ptr [ebp-44h],eax
string test2 = "";
0000003a mov eax,dword ptr ds:[022A202Ch]
00000040 mov dword ptr [ebp-40h],eax
string test22 = test2;
00000043 mov eax,dword ptr [ebp-40h]
00000046 mov dword ptr [ebp-44h],eax
Najlepszy kod w ogóle nie ma kodu :
Podstawowa natura kodowania polega na tym, że naszym zadaniem jako programistów jest uznanie, że każda decyzja, którą podejmujemy, jest kompromisem. […] Zacznij od zwięzłości. Zwiększ inne wymiary zgodnie z wymaganiami testu.
W rezultacie, mniej kod jest lepszy kod: Wolę ""
się string.Empty
lub String.Empty
. Te dwa są sześć razy dłuższe bez dodatkowej korzyści - z pewnością bez dodatkowej przejrzystości, ponieważ wyrażają dokładnie te same informacje.
i
jest lepsza niż długa nazwa zmiennej. Zawsze bardziej preferowane są nawet bardziej ogólne, krótsze nazwy zmiennych, które przekazują te same informacje , w tej samej przejrzystości. Po prostu, aby wyrazić niezbędne informacje, potrzebujesz pewnej długości postaci i nie zaprzeczam temu (nikt nie jest).
Jedną różnicą jest to, że jeśli używasz switch-case
składni, nie możesz pisać, case string.Empty:
ponieważ nie jest to stała. DostajeszCompilation error : A constant value is expected
Spójrz na ten link, aby uzyskać więcej informacji: string-empty-versus-empty-quotes
switch
stwierdzenie jest bardzo dobrym przykładem. Ponadto, jeśli podasz parametr opcjonalny, np void MyMethod(string optional = "") { ... }
. Nie będzie można go użyć string.Empty
. A potem oczywiście, jeśli chcesz zdefiniować const
pole lub zmienną lokalną, const string myString = "";
znowu ""
jest jedyną opcją. Gdyby tylko string.Empty
było stałym polem, nie byłoby różnicy. Ale tak nie jest, więc w niektórych przypadkach musisz użyć ""
. Dlaczego więc nie korzystać ""
cały czas?
string.Empty
uniemożliwia osiągnięcie spójności w bazie kodu: musisz użyć dwóch różnych bytów, aby wyrazić to samo. I dodać do listy rzeczy, których nie możesz zrobić: nie możesz używać string.Empty
z atrybutami .
Wolałbym string
się String
. Wybierając się string.Empty
na ""
to kwestia wyboru jednego i wystaje z niego. Zaletą używania string.Empty
jest to, że masz na myśli to, co masz na myśli, i nie kopiujesz przypadkowo znaków niedrukowalnych, jak "\x003"
w twoim ""
.
""
jest niebezpieczny, gdy kopiowanie / wklejanie jest nieważny, twierdzę, ponieważ nigdy nie kopiujesz / wklejasz pustego łańcucha. Oczywiście w przypadku innych łańcuchów zawsze należy pamiętać.
Nie zamierzałem się wtrącać, ale widzę, że wyrzucano tutaj złe informacje.
Ja osobiście wolę string.Empty
. To jest osobista preferencja i przychylam się do woli każdego zespołu, z którym pracuję na zasadzie indywidualnej.
Jak wspomnieli inni, nie ma żadnej różnicy między string.Empty
i String.Empty
.
Ponadto jest to mało znany fakt, że użycie „” jest całkowicie dopuszczalne. Każde wystąpienie „” w innych środowiskach utworzy obiekt. Jednak .NET internalizuje swoje łańcuchy, więc przyszłe instancje wyciągną ten sam niezmienny ciąg z puli wewnętrznej, a każde uderzenie wydajności będzie znikome. Źródło: Brad Abrams .
Osobiście wolę „”, chyba że istnieje uzasadniony powód do czegoś bardziej złożonego.
String.Empty
i string.Empty
są równoważne. String
to nazwa klasy BCL; string
to jego alias C # (lub skrót, jeśli chcesz). To samo co z Int32
i int
. Zobacz dokumenty, aby uzyskać więcej przykładów.
Jeśli chodzi ""
o mnie, nie jestem do końca pewien.
Osobiście zawsze używam string.Empty
.
Prawie każdy programista będzie wiedział, co znaczy „”. Osobiście zetknąłem się z String.Empty po raz pierwszy i musiałem poświęcić trochę czasu na wyszukiwanie w Google, aby dowiedzieć się, czy naprawdę są dokładnie takie same.
string.Empty
? Czy wiesz, jaki ""
był pierwszy raz?
Ten temat jest dość stary i długi, więc przepraszam, jeśli takie zachowanie zostało wspomniane gdzie indziej. (I wskaż mi odpowiedź na to pytanie)
Znalazłem różnicę w zachowaniu kompilatora, jeśli używasz string.Empty
lub cudzysłowu. Różnica pokazuje się, jeśli nie używasz zmiennej łańcuchowej zainicjowanej ciągiem znaków. Puste lub z podwójnymi cudzysłowami.
W przypadku inicjalizacji z string.Empty
tym ostrzeżeniem kompilatora
CS0219 - The variable 'x' is assigned but its value is never used
nigdy nie jest emitowany, podczas gdy w przypadku inicjowania podwójnymi cudzysłowami pojawia się oczekiwany komunikat.
To zachowanie wyjaśniono w artykule Connect pod tym linkiem: https://connect.microsoft.com/VisualStudio/feedback/details/799810/c-warning-cs0219-not-reported-when-assign-non-constant-value
Zasadniczo, jeśli dobrze to zrozumiem, chcą pozwolić programistowi ustawić zmienną z wartością zwracaną funkcji do celów debugowania bez zawracania mu głowy ostrzeżeniem, a zatem ograniczają ostrzeżenie tylko w przypadku kosztownych przypisań i łańcucha. Puste nie jest stałą, ale polem.
var unused = "literal";
kompilator może całkowicie zoptymalizować (usunąć) deklarację . Nie może powodować żadnych skutków ubocznych. Z drugiej strony var unused = MyClass.Member;
nie można go całkowicie usunąć. To dlatego, że czytanie Member
może mieć skutki uboczne. Jeśli Member
jest to właściwość statyczna z get
akcesorium, jasne jest, że połączenie z modułem pobierającym musi zostać zachowane. Ale nawet jeśli Member
jest to pole statyczne, może wystąpić efekt uboczny, który może uruchomić konstruktor statyczny. Jasne, że taki sposób kodowania byłby zły . Ale potrzebujesz manekina do czytania Member
.
Ten bardzo prosty test wykonałem przy użyciu następującej metody w aplikacji konsolowej:
private static void CompareStringConstants()
{
string str1 = "";
string str2 = string.Empty;
string str3 = String.Empty;
Console.WriteLine(object.ReferenceEquals(str1, str2)); //prints True
Console.WriteLine(object.ReferenceEquals(str2, str3)); //prints True
}
To wyraźnie sugeruje, że wszystkie trzy zmienne mianowicie str1
, str2
i str3
chociaż są inicjowane przy użyciu innej składni, wskazują dokładnie ten sam obiekt (o zerowej długości) w pamięci. Test wykonałem w aplikacji konsoli .NET 4.5. Więc wewnętrznie nie mają różnicy, a wszystko sprowadza się do wygody, której chcesz użyć jako programisty. To zachowanie klasy ciągów jest znane jako internowanie ciągów w .NET. Eric Lippert ma bardzo ładny blog tutaj opisujący tę koncepcję.
Dowolne z powyższych.
Jest wiele lepszych rzeczy do pontyfikatu. Jak na przykład kolor kory najlepiej pasuje do drzewa, myślę, że jest niejasny brąz z odcieniami mchu cielęcego.
Zdecydowanie wolę String.Empty, oprócz innych powodów, aby upewnić się, że wiesz, co to jest i że nie usunąłeś przypadkowo treści, ale przede wszystkim w celu internacjonalizacji. Jeśli widzę ciąg znaków w cudzysłowie, zawsze muszę się zastanawiać, czy jest to nowy kod i należy go umieścić w tabeli ciągów. Więc za każdym razem, gdy kod jest zmieniany / sprawdzany, musisz szukać „czegoś w cudzysłowach” i tak, możesz odfiltrować puste ciągi znaków, ale mówię ludziom, że dobrą praktyką jest, aby nigdy nie wstawiać ciągów znaków w cudzysłowie, chyba że wiesz, że nie zostanie ono zlokalizowane .
Nikt nie wspominał, że w VisualStudio String jest kodowany kolorem inaczej niż string. Co jest ważne dla czytelności. Również małe litery są zwykle używane dla zmiennych i typów, nie jest to wielka sprawa, ale String.Empty jest stałą, a nie zmienną ani typem.
string
jest synonimem System.String
typu, są identyczne.
Wartości są również identyczne: string.Empty == String.Empty == ""
Nie chciałbym używać stałej znaków „” w kodzie, raczej string.Empty
lub String.Empty
- łatwiej zobaczyć co programista miał na myśli.
Pomiędzy string
i bardziej String
lubię małe litery string
tylko dlatego, że pracowałem z Delphi przez wiele lat, a styl Delphi jest pisany małymi literami string
.
Więc gdybym był twoim szefem, pisałbyś string.Empty
Chciałbym sprzyjać string.Empty
nad String.Empty
dlatego można go używać bez konieczności obejmują using System;
w pliku.
Jeśli chodzi o zbieranie ""
ciągu string.Empty
jest to osobiste preferencje i powinny być podejmowane przez zespół.
string.Empty
stałej bez importowania using System
przestrzeni nazw - słowa kluczowe w C # po prostu przekonwertuj na ich w pełni kwalifikowaną nazwę, która obejmuje również przestrzeń nazw, zanim zostanie zapisana jako MSIL na wyjściu * .dll lub *. plik exe. Tak skutecznie string.Empty
zostaje zapisany System.String.Empty
przez kompilator jak w MSIL. A ponieważ już wiesz, że jeśli podasz pełną nazwę typu, możesz pominąć importowanie przestrzeni nazw u góry pliku kodu.
Nie robię różnicy. Ten ostatni jest jednak najszybszy do wpisania :)
To nie ma znaczenia - są dokładnie takie same. Najważniejsze jest jednak, abyś był konsekwentny
ps Cały czas walczę z tego rodzaju „co jest właściwe”.
Jest to całkowicie preferencja stylu kodu, rób, jak .NET obsługuje ciągi znaków. Oto moje opinie :)
Przy dostępie do statycznych metod, właściwości i pól zawsze używać nazw BCL Typ: String.Empty
lub Int32.TryParse(...)
lubDouble.Epsilon
Zawsze używam słów kluczowych C # przy deklarowaniu nowych instancji: int i = 0;
lubstring foo = "bar";
Rzadko używam niezadeklarowanych literałów łańcuchowych, ponieważ lubię mieć możliwość skanowania kodu w celu połączenia ich w nazwane stałe wielokrotnego użytku. Kompilator i tak zastępuje stałe literałami, więc jest to raczej sposób na uniknięcie magicznych ciągów / liczb i nadanie im trochę więcej znaczenia dzięki nazwie. Plus zmiana wartości jest łatwiejsza.
Każde z dwóch pierwszych byłoby dla mnie do zaakceptowania. Unikałbym tego ostatniego, ponieważ stosunkowo łatwo jest wprowadzić błąd, umieszczając odstęp między cudzysłowami. Ten konkretny błąd byłby trudny do znalezienia przez obserwację. Zakładając brak literówek, wszystkie są semantycznie równoważne.
[EDYTOWAĆ]
Ponadto, warto zawsze użyć jednej string
lub String
dla spójności, ale to tylko moje zdanie.
Osobiście byłem świadkiem „” powodujących (niewielkie) problemy dwukrotnie. Kiedyś był to błąd młodszego programisty, który był nowy w programowaniu zespołowym, a drugi to zwykła literówka, ale faktem jest ciąg znaków. Puste uniknęłoby obu problemów.
Tak, jest to w dużej mierze wezwanie do osądu, ale gdy język daje wiele sposobów robienia rzeczy, zwykle skłaniam się ku temu, który ma największy nadzór kompilatora i najsilniejsze wymuszanie czasu kompilacji. To nie jest „”. Chodzi o wyrażanie konkretnych intencji.
Jeśli wpiszesz string.EMpty lub Strng.Empty, kompilator poinformuje cię, że zrobiłeś to źle. Natychmiast. Po prostu się nie skompiluje. Jako programista powołujesz się na konkretną intencję, że kompilator (lub inny programista) nie może w żaden sposób źle interpretować, a gdy zrobisz to źle, nie możesz stworzyć błędu.
Jeśli wpiszesz „”, gdy masz na myśli „” lub odwrotnie, kompilator z radością zrobi to, co mu kazałeś. Inny programista może, ale nie musi, poznać twoją konkretną intencję. Błąd został utworzony.
Na długo przed string.Empty był rzeczą, której użyłem standardowej biblioteki, która zdefiniowała stałą EMPTY_STRING. Nadal używamy tej stałej w instrukcjach case, w których string.Empty jest niedozwolone.
O ile to możliwe, włącz kompilator, aby działał dla Ciebie i wyeliminuj możliwość błędu ludzkiego, bez względu na to, jak mały. IMO przebija „czytelność”, jak cytowali inni.
Specyfika i wymuszanie czasu kompilacji. To jest na obiad.
Kompilator powinien uczynić je takimi samymi na dłuższą metę. Wybierz standard, aby kod był łatwy do odczytania i trzymaj się go.
Właśnie patrzyłem na jakiś kod i to pytanie przyszło mi do głowy, które czytałem już jakiś czas. Z pewnością jest to kwestia czytelności.
Rozważ następujący kod C # ...
(customer == null) ? "" : customer.Name
vs
(customer == null) ? string.empty : customer.Name
Osobiście uważam to drugie za mniej dwuznaczne i łatwiejsze do odczytania.
Jak zauważyli inni, rzeczywiste różnice są znikome.
Chociaż różnica jest bardzo, BARDZO mała, różnica wciąż istnieje.
1) „” tworzy obiekt, a String.Empty nie. Ale ten obiekt zostanie utworzony jeden raz i będzie później przywoływany z puli ciągów, jeśli masz inny kod w kodzie.
2) Ciąg znaków i ciąg znaków są takie same, ale zalecałbym użycie String.Empty (jak również String.Format, String.Copy itp.), Ponieważ notacja kropkowa wskazuje klasę, a nie operator, a klasa zaczynająca się od dużej litery jest zgodna z Standardy kodowania C #.
Na http://blogs.msdn.com/b/brada/archive/2003/04/22/49997.aspx :
Jak sugeruje Dawid, różnice między
String.Empty
i""
są dość małe, ale jest różnica.""
faktycznie tworzy obiekt, prawdopodobnie zostanie wyciągnięty z wewnętrznej puli ciągów znaków, ale nadal ... podczas gdyString.Empty
nie tworzy żadnego obiektu ... więc jeśli naprawdę szukasz ostatecznej wydajności pamięci, sugerujęString.Empty
. Należy jednak pamiętać, różnica jest tak TRIVAL będzie jak nigdy zobaczyć go w kodzie ...
jak naSystem.String.Empty
lubstring.Empty
lubString.Empty
... mój poziom opieki jest niski ;-)
Pusty ciąg jest jak pusty zestaw, po prostu nazwa, którą wszyscy używają do wywołania ""
. Również w językach formalnych ciągi utworzone z alfabetu o zerowej długości są nazywane ciągiem pustym. Zarówno zestaw, jak i łańcuch mają dla niego specjalny symbol. Pusty ciąg: ε i pusty zestaw: ∅. Jeśli chcesz porozmawiać o tym łańcuchu o zerowej długości, nazwiesz go pustym ciągiem, aby wszyscy wiedzieli dokładnie, o czym mówisz. Teraz, jeśli nazwiesz go pustym ciągiem, dlaczego nie użyć string.Empty
w kodzie, jego zamiary są wyraźne. Minusem jest to, że nie jest stała i dlatego nie jest dostępna wszędzie, jak w atrybutach. (Z pewnych przyczyn technicznych nie jest stała, zobacz źródło odniesienia).
Wolę, ""
ponieważ jest krótszy i String.Empty
rozwiązuje problem, który nie istnieje.