Czytam Efektywny C # autorstwa Billa Wagnera. W punkcie 14 - Minimize Duplicate Initialization Logic , przedstawia on następujący przykład użycia nowej funkcji parametrów opcjonalnych w konstruktorze:
public MyClass(int initialCount = 0, string name = "")
Zauważ, że użył ""
zamiast string.Empty
.
On komentuje:
Zauważysz [w powyższym przykładzie], że drugi konstruktor określił „” jako domyślną wartość parametru name , a nie bardziej zwyczajową
string.Empty
. Dzieje się tak, ponieważstring.Empty
nie jest to stała czasu kompilacji. Jest to statyczna właściwość zdefiniowana w klasie string. Ponieważ nie jest to stała kompilacji, nie można jej użyć jako wartości domyślnej parametru.
Jeśli nie możemy użyć string.Empty
statyki we wszystkich sytuacjach, czy nie jest to sprzeczne z jej celem? Pomyślałem, że użyjemy go, aby upewnić się, że mamy niezależny od systemu sposób odwoływania się do pustego łańcucha. Czy moje zrozumienie jest złe? Dzięki.
UPDATE
Tylko komentarz uzupełniający. Według MSDN:
Każdy opcjonalny parametr ma wartość domyślną jako część swojej definicji. Jeśli dla tego parametru nie zostanie przesłany żaden argument, używana jest wartość domyślna. Wartości domyślne muszą być stałymi.
W takim przypadku nie będziemy mogli System.Environment.NewLine
ani używać ani używać nowo utworzonych obiektów jako wartości domyślnych. Nie korzystałem jeszcze z VS2010 i to jest rozczarowujące!
źródło
Odpowiedzi:
Podobnie jak w przypadku kompilatora C # 2.0, i tak nie ma to większego sensu
String.Empty
, aw rzeczywistości w wielu przypadkach jest to pesymizacja, ponieważ kompilator może wstawić niektóre odniesienia do,""
ale nie może zrobić tego samego zString.Empty
.W C # 1.1 warto było unikać tworzenia wielu niezależnych obiektów zawierających pusty ciąg, ale te czasy już minęły.
""
działa dobrze.źródło
Nic nie stoi na przeszkodzie, aby zdefiniować własną stałą dla pustego ciągu, jeśli naprawdę chcesz go użyć jako opcjonalnej wartości parametru:
const string String_Empty = ""; public static void PrintString(string s = String_Empty) { Console.WriteLine(s); }
[Tak na marginesie, jednym z powodów wolą
String.Empty
nad""
w ogóle, które nie zostały wymienione w innych odpowiedzi, jest to, że istnieją różne znaki Unicode (zero-width stolarzy, etc.), które są skutecznie niewidoczne gołym okiem. Więc coś, co wygląda,""
niekoniecznie jest pustym ciągiem, podczas gdyString.Empty
wiesz dokładnie, czego używasz. Rozumiem, że to nie jest częste źródło błędów, ale jest to możliwe.]źródło
Z pierwotnego pytania:
W jaki sposób pusty ciąg może różnić się w zależności od systemu? To zawsze ciąg bez znaków! Byłbym naprawdę przerażony, gdybym kiedykolwiek znalazł implementację, która
string.Empty == ""
zwróciłaby fałsz :) To nie to samo, co coś podobnegoEnvironment.NewLine
.Z postu o zleceniach antyterrorystycznych:
Cóż, to z pewnością się nie wydarzy.
Chociaż osobiście wolałbym również bardzo inny mechanizm domyślny, sposób działania parametrów opcjonalnych był w .NET od samego początku - i zawsze oznacza to osadzenie stałej w metadanych, tak aby kod wywołujący mógł skopiować tę stałą do wywołania witryna, jeśli nie zostanie podany odpowiedni argument.
Ze
string.Empty
to naprawdę bezcelowe - używając""
będą robić to, co chcesz; czy używanie dosłownego ciągu znaków jest takie bolesne? (Wszędzie używam dosłownego - nigdy nie używamstring.Empty
- ale to inny argument).Właśnie to mnie zaskakuje w tym pytaniu - skarga obraca się wokół czegoś, co tak naprawdę nie powoduje prawdziwego problemu. Jest to ważniejsze w przypadkach, gdy chcesz, aby wartość domyślna była obliczana w czasie wykonywania, ponieważ w rzeczywistości może się różnić. Na przykład, mógłbym sobie wyobrazić przypadki, w których chciałbyś móc wywołać metodę z
DateTime
parametrem i ustawić ją jako domyślną na „aktualny czas”. W tej chwili jedyne mało eleganckie obejście tego problemu, jakie znam, to:public void RecordTime(string message, DateTime? dateTime = null) { var realDateTime = dateTime ?? DateTime.UtcNow; }
... ale to nie zawsze jest właściwe.
Podsumowując:
string.Empty
tak jest to bezceloweźródło
Environment.Newline
... Jedyne, czego brakuje w twoim przykładzie, to sprawdzenie zmiennej pod kątem wartości null i zwrócenie wyjątku z powrotem do programisty, mówiąc mu, że chociaż dopuszcza wartość null, to nie zaakceptowany.if(dateTime == null){ throw new ArgumentException("The dateTime parameter must be set. Nullable type used for device independent variable set.");}
czy coś takiego. Ale naprawdę to lubię! Masz inne zastrzeżenia, aby zrobić to po swojemu?Nigdy nie używam stringów, puste, nie widzę w tym sensu. Może jest to łatwiejsze dla ludzi, którzy są naprawdę nowicjuszami w programowaniu, ale wątpię, by było to przydatne nawet do tego.
źródło
""
i" "
, ale nie mogę powiedzieć, że" "
to wszystko jest takie powszechne.Myślę, że ideą string.Empty jest to, że poprawia czytelność. To nie jest jak nowa linia, w której istnieje różnica między tym, jak jest reprezentowana na różnych platformach. Szkoda, że nie można go użyć w parametrze domyślnym. Jednak nie spowoduje to żadnych problemów, jeśli połączysz system Windows z czymś takim jak Mono w systemie Linux.
źródło
String.Empty
bardziej czytelne. . . osobiście jednak uważam, że to trochę zwariowane.""
jest prawdopodobnie najpowszechniejszym ciągiem, jaki istnieje i każdy widział go miliard razy, więc jak jest nieczytelny?String.Empty
jest tak samo przydatne, jakby istniał plikInt32.Zero
.Jako FYI wygląda na to, że to samo ograniczenie jest nakładane na wartości przekazywane do konstruktorów atrybutów - muszą one być stałe. Ponieważ string.empty jest zdefiniowany jako:
public static readonly string Empty
raczej niż rzeczywista stała, nie może być używana.
źródło
Używam
string.Empty
wyłącznie dla czytelności.Jeśli ktoś inny będzie musiał później przeczytać / zmienić mój kod, wie, że zamierzałem sprawdzić lub ustawić coś na pusty ciąg. Używanie po prostu
""
może czasami powodować błędy i zamieszanie, ponieważ mogłem po prostu zapomnieć o umieszczeniu tam ciągu, który chciałem.Na przykład:
if(someString == string.Empty) { }
vs
if(someString == "") { }
Pierwsze
if
stwierdzenie wydaje mi się o wiele bardziej przemyślane i czytelne. Ponieważ jest to jednak tylko preferencja, naprawdę nie widzę rozbijania pociągu w konieczności używania""
zamiaststring.Empty
.źródło
Być może najlepszym rozwiązaniem tego problemu jest przeciążenie tej metody w ten sposób:
public static void PrintString() { PrintString(string.Empty); }
źródło