Zawsze inicjowałem moje ciągi na NULL, myśląc, że NULL oznacza brak wartości, a „” lub String.Empty jest prawidłową wartością. Widziałem ostatnio więcej przykładów kodu, w którym String.Empty jest uważana za wartość domyślną lub nie reprezentuje żadnej wartości. Wydaje mi się to dziwne, ponieważ z nowo dodanymi typami dopuszczającymi wartość null w c # wydaje się, że cofamy się o ciągi, nie używając wartości NULL do reprezentowania `` Brak wartości ''.
Czego używasz jako domyślnego inicjatora i dlaczego?
Edycja: W oparciu o odpowiedzi, kontynuuję moje dalsze przemyślenia
Unikanie obsługi błędów Jeśli wartość nie powinna być zerowa, dlaczego została ustawiona na
NULL
w pierwszej kolejności? Może lepiej byłoby zidentyfikować błąd w miejscu, w którym występuje, zamiast ukrywać go w pozostałej części kodu?Unikanie sprawdzania wartości null Jeśli masz dość sprawdzania wartości null w kodzie, czy nie byłoby lepiej abstrakcyjnie sprawdzać wartości null? Być może zawiń (lub rozszerz!) Metody łańcuchowe, aby były
NULL
bezpieczne? Co się dzieje, jeśli ciągle używaszString.Empty
i zdarza się, że null działa w twoim systemie, czy mimo wszystko zaczniesz dodawaćNULL
sprawdzenia?
Nie mogę się powstrzymać od powrotu do opinii, że to lenistwo. Każdy DBA spoliczkowałby cię na dziewięć sposobów, gdybyś użył „” zamiast null
w swojej \ jej bazie danych. Myślę, że te same zasady obowiązują w programowaniu i powinien być ktoś, kto uderzy w głowę tych, którzy używają, String.Empty
a nie NULL
reprezentują żadnej wartości.
Powiązane pytania
Odpowiedzi:
+1 za rozróżnienie między „pustym” a NULL. Zgadzam się, że „puste” powinno oznaczać „ważne, ale puste”, a „NULL” powinno oznaczać „nieważne”.
Więc odpowiedziałbym na twoje pytanie w ten sposób:
puste, gdy chcę mieć prawidłową wartość domyślną, która może lub nie może zostać zmieniona, na przykład drugie imię użytkownika.
NULL, gdy jest to błąd, jeśli wynikowy kod nie ustawia jawnie wartości.
źródło
Według MSDN :
IsNullOrEmpty()
Niemniej jednak używanie zawsze jest dobrą praktyką.źródło
Dlaczego chcesz w ogóle zainicjować swój łańcuch? Nie musisz inicjować zmiennej, gdy ją deklarujesz, i IMO, powinieneś to zrobić tylko wtedy, gdy przypisywana wartość jest prawidłowa w kontekście bloku kodu.
Często to widzę:
string name = null; // or String.Empty if (condition) { name = "foo"; } else { name = "bar"; } return name;
Brak inicjalizacji do wartości null byłby równie skuteczny. Ponadto najczęściej chcesz przypisać wartość. Inicjując wartość null, można potencjalnie przegapić ścieżki kodu, które nie przypisują wartości. Tak jak to:
string name = null; // or String.Empty if (condition) { name = "foo"; } else if (othercondition) { name = "bar"; } return name; //returns null when condition and othercondition are false
Jeśli nie zainicjujesz wartości null, kompilator wygeneruje błąd informujący, że nie wszystkie ścieżki kodu przypisują wartość. Oczywiście to bardzo prosty przykład ...
Matthijs
źródło
= null
) wygenerowałaby ostrzeżenie, dokładnie z podanego przez ciebie powodu - nie ma znaczenia, czy domyślna wartość ciągu jest pusta. jeśli nie gwarantujesz przypisania przez każdą ścieżkę kodu, IDE (i / lub przypuszczam, że bazowy kompilator [?]) wygeneruje ostrzeżenie. Chociaż ostrzeżenia nie uniemożliwiają kompilacji, nadal istnieją - pozostawienie tych, które można łatwo rozwiązać, może pomóc zaciemnić inne, które mogą zasługiwać na uwagę programistyname
tonull
(brak ostrzeżeń), ponieważ każda ścieżka kodu przypisuje wartośćname
- nie ma potrzeby inicjowania w ogóleW przypadku większości programów, które w rzeczywistości nie są oprogramowaniem do przetwarzania ciągów, logika programu nie powinna zależeć od zawartości zmiennych łańcuchowych. Ilekroć zobaczę coś takiego w programie:
if (s == "value")
Mam złe przeczucie. Dlaczego w tej metodzie występuje ciąg znaków? Jakie jest ustawienie
s
? Czy wie, że logika zależy od wartości ciągu? Czy wie, że aby zadziałało, musi to być małe litery? Czy powinienem to naprawić, zmieniając go na użycieString.Compare
? Czy powinienem tworzyćEnum
i analizować w nim plik ?Z tej perspektywy można dojść do filozofii kodu, która jest dość prosta: unikasz badania zawartości łańcucha, gdy tylko jest to możliwe. Porównywanie ciągu znaków
String.Empty
to tak naprawdę szczególny przypadek porównywania go z literałem: jest to coś, czego należy unikać, chyba że naprawdę musisz.Wiedząc to, nie mrugam, gdy widzę coś takiego w naszej bazie kodu:
string msg = Validate(item); if (msg != null) { DisplayErrorMessage(msg); return; }
Wiem, że
Validate
to nigdy nie wróciString.Empty
, ponieważ piszemy lepszy kod niż to.Oczywiście reszta świata nie działa w ten sposób. Kiedy twój program zajmuje się wprowadzaniem danych przez użytkownika, bazami danych, plikami itd., Musisz wziąć pod uwagę inne filozofie. Tam zadaniem twojego kodu jest narzucenie porządku w chaosie. Częścią tego porządku jest wiedza, kiedy pusty łańcuch powinien oznaczać,
String.Empty
a kiedy powinien oznaczaćnull
.(Żeby upewnić się, że nie mówię z siebie, przeszukałem tylko naszą bazę kodów pod kątem `String.IsNullOrEmpty '. Wszystkie 54 wystąpienia tego występują w metodach, które przetwarzają dane wejściowe użytkownika, zwracają wartości ze skryptów Pythona, sprawdzają wartości pobrane z zewnętrzne interfejsy API itp.)
źródło
W rzeczywistości jest to ziejąca dziura w języku C #. Nie ma możliwości zdefiniowania łańcucha, który nie może mieć wartości null. Powoduje to problemy tak proste, jak ten, który opisujesz, co zmusza programistów do podjęcia decyzji, której nie powinni podejmować, ponieważ w wielu przypadkach NULL i String.Empty oznaczają to samo. To z kolei może później zmusić innych programistów do obsługi zarówno wartości NULL, jak i String.Empty, co jest denerwujące.
Większy problem polega na tym, że bazy danych umożliwiają definiowanie pól, które są mapowane na ciąg C #, ale pola bazy danych można zdefiniować jako NIE NULL. Nie ma więc sposobu, aby dokładnie przedstawić, powiedzmy, pole varchar (100) NOT NULL w SQL Server przy użyciu typu C #.
Inne języki, takie jak Spec #, pozwalają na to.
Moim zdaniem niezdolność C # do zdefiniowania łańcucha, który nie zezwala na null, jest tak samo zła, jak jego poprzednia niezdolność do zdefiniowania int, która dopuszcza null.
Aby w pełni odpowiedzieć na twoje pytanie: zawsze używam pustego ciągu do domyślnej inicjalizacji, ponieważ jest on bardziej podobny do sposobu działania typów danych w bazie danych. (Edycja: To stwierdzenie było bardzo niejasne. Powinno brzmieć: „Używam pustego ciągu do domyślnej inicjalizacji, gdy NULL jest stanem zbędnym, podobnie jak ustawiłem kolumnę bazy danych jako NOT NULL, jeśli NULL byłby stanem zbędnym. , wiele moich kolumn DB jest skonfigurowanych jako NIE NULL, więc kiedy wprowadzam je do ciągu C #, ciąg będzie pusty lub będzie miał wartość, ale nigdy nie będzie NULL. Innymi słowy, inicjalizuję tylko ciąg na NULL jeśli null ma znaczenie inne niż znaczenie String.Empty i uważam, że ten przypadek jest mniej niż powszechny (ale ludzie tutaj podali uzasadnione przykłady tego przypadku). ")
źródło
To zależy.
Czy musisz być w stanie stwierdzić, czy brakuje wartości (czy jest możliwe, że nie zostanie ona zdefiniowana)?
Czy pusty ciąg jest prawidłową wartością do użycia tego ciągu?
Jeśli odpowiedziałeś „tak” na oba, będziesz chciał użyć null. W przeciwnym razie nie możesz odróżnić „bez wartości” od „pustego ciągu znaków”.
Jeśli nie musisz wiedzieć, czy nie ma wartości, pusty łańcuch jest prawdopodobnie bezpieczniejszy, ponieważ pozwala pominąć sprawdzanie null, gdziekolwiek go używasz.
źródło
wygląda na to, że jest to szczególny przypadek http://en.wikipedia.org/wiki/Null_Object_pattern
źródło
Ustawiam ją na „” lub null - zawsze sprawdzam za pomocą String.IsNullOrEmpty, więc oba są w porządku.
Ale wewnętrzny maniak we mnie mówi, że powinienem ustawić go na zero, zanim będę miał dla niego odpowiednią wartość ...
źródło
Zawsze deklaruję ciąg za pomocą string.empty;
źródło
Czy to możliwe, że jest to technika unikania błędów (zalecana czy nie ...)? Ponieważ „” nadal jest łańcuchem znaków, można by wywołać na nim funkcje łańcuchowe, które spowodowałyby wyjątek, gdyby miał wartość NULL?
źródło
Zawsze inicjalizuję je jako
NULL
.I zawsze korzystać
string.IsNullOrEmpty(someString)
, aby sprawdzić jego wartość.Prosty.
źródło
To zależy od sytuacji. W większości przypadków używam String.Empty, ponieważ nie chcę sprawdzać wartości null za każdym razem, gdy próbuję użyć ciągu. To znacznie upraszcza kod i jest mniej prawdopodobne, że wprowadzisz niechciane awarie NullReferenceException.
Ustawiam ciąg na null tylko wtedy, gdy muszę wiedzieć, czy został ustawiony, czy nie i gdzie pusty ciąg jest prawidłowy, aby go ustawić. W praktyce takie sytuacje są rzadkie.
źródło
Pusty ciąg to wartość (fragment tekstu, który, nawiasem mówiąc, nie zawiera żadnych liter). Null oznacza brak wartości.
Inicjalizuję zmienne na null, gdy chcę wskazać, że nie wskazują one ani nie zawierają rzeczywistych wartości - gdy intencją jest brak wartości.
źródło
Powtarzając odpowiedź Tomalaka, pamiętaj, że kiedy przypiszesz zmienną łańcuchową do wartości początkowej null, twoja zmienna nie będzie już obiektem typu string; to samo z każdym obiektem w C #. Tak więc, jeśli spróbujesz uzyskać dostęp do jakichkolwiek metod lub właściwości swojej zmiennej i zakładasz, że jest to obiekt ciągu, otrzymasz wyjątek NullReferenceException.
źródło
Null należy używać tylko w przypadkach, gdy wartość jest opcjonalna. Jeśli wartość nie jest opcjonalna (np. „Nazwa” lub „Adres”), wówczas wartość nigdy nie powinna być pusta. Dotyczy to baz danych, a także POCO i interfejsu użytkownika. Null oznacza „ta wartość jest opcjonalna i obecnie jej nie ma”.
Jeśli twoje pole nie jest opcjonalne, powinieneś zainicjować je jako pusty ciąg. Zainicjowanie go jako null spowoduje umieszczenie obiektu w nieprawidłowym stanie (nieprawidłowym według własnego modelu danych).
Osobiście wolałbym, aby łańcuchy domyślnie nie dopuszczały wartości null, ale zamiast tego dopuszczały wartość null tylko wtedy, gdy zadeklarujemy „ciąg?”. Chociaż być może nie jest to wykonalne lub logiczne na głębszym poziomie; niepewny.
źródło
Łańcuchy nie są typami wartości i nigdy nie będą ;-)
źródło
Myślę, że nie ma powodu, aby nie używać wartości null dla nieprzypisanej (lub w tym miejscu w przepływie programu) wartości. Jeśli chcesz rozróżnić, jest == null. Jeśli chcesz tylko sprawdzić pewną wartość i nie obchodzi Cię, czy jest to wartość null, czy coś innego, String.Equals („XXX”, MyStringVar) działa dobrze.
źródło