To pytanie może rozwiązać to pytanie, krótka odpowiedź brzmi: nikt nie wie ...
gdoron wspiera Monikę
Tak, +1 za odpowiedź Erica Lipperta, dziękuję!
travis,
Szczególnie biorąc pod uwagę, że Decimal.Zero jest const (z perspektywy użytkownika, czyli ...)
Hamish Grubijan,
Odpowiedzi:
148
Powodem static readonlyużycia zamiast tego constjest użycie niezarządzanego kodu, jak wskazał Microsoft tutaj w wersji Shared Source Common Language Infrastructure 2.0 . Plik do obejrzenia to sscli20\clr\src\bcl\system\string.cs.
Stała pusta przechowuje wartość pustego ciągu. Musimy wywołać konstruktor String, aby kompilator nie oznaczył tego jako literału.
Oznaczenie tego jako literału oznaczałoby, że nie pojawia się jako pole, do którego możemy uzyskać dostęp z natywnego.
@gdoron: Moje przypuszczenie (i przypuszczenie) jest takie. Kiedy wartość jest zdefiniowana jako literał (stała), jej wartość jest wstawiana w miejsca, do których się odwołuje, podczas gdy gdy nie jest zdefiniowana jako literał, źródło wartości jest wskazywane, a rzeczywista wartość jest pobierana w czasie wykonywania. Podejrzewam, że ten ostatni może zapewnić, że prawidłowe zestawienie ciągu wystąpi między natywnym a .NET w czasie wykonywania - gdyby był literałem, być może macierzysty kompilator musiałby w jakiś sposób wciągnąć literalną wartość do swojego natywnego kodu, co prawdopodobnie nie jest wykonalny. To wszystko jest jednak domniemanie z mojej strony.
Jeff Yates,
7
Oznacza to, że należy użyć „”, a nie łańcucha. Puste dla domyślnych wartości parametrów w metodach. Co jest nieco denerwujące.
nicodemus13
17
„” może wyglądać jak błąd, podczas gdy string. Puste pokazuje celowe zamiary
Christopher Stevenson
3
@JeffYates Dodam, że fakt, że nie jest spójny, jest już denerwujący. Ludzie zobaczą resztę kodu i zastanawiają się, „dlaczego on używa tutaj” zamiast String.Empty? ”. Poważnie zastanawiam się nad nieużywaniem String.Emptyjuż tylko z tego powodu.
julealgon
24
Myślę, że jest tu wiele zamieszania i złych odpowiedzi.
Przede wszystkim constpola są staticczłonkami ( nie członkami instancji ).
Sprawdź rozdział 10.4 Stałe specyfikacji języka C #.
Mimo że stałe są uważane za elementy statyczne, deklaracja stała nie wymaga ani nie pozwala na modyfikator statyczny.
Jeśli public constczłonkowie są statyczni, nie można uznać, że stała utworzy nowy Obiekt.
Biorąc to pod uwagę, poniższe wiersze kodu robią dokładnie to samo w odniesieniu do tworzenia nowego obiektu.
Oto uwaga od Microsoft, która wyjaśnia różnicę między 2:
Słowo kluczowe tylko do odczytu różni się od słowa kluczowego const. Pole const można zainicjować tylko w deklaracji pola. Pole tylko do odczytu można zainicjować w deklaracji lub w konstruktorze. Dlatego pola tylko do odczytu mogą mieć różne wartości w zależności od zastosowanego konstruktora. Ponadto, chociaż pole const jest stałą czasu kompilacji, pole tylko do odczytu może być użyte do stałych środowiska wykonawczego, ...
Uważam więc, że jedyną możliwą odpowiedzią jest odpowiedź Jeffa Yatesa.
+1 za miłe słowa i wyjaśnienia dotyczące specyfikacji C # dla const i static readonly.
Jeff Yates
17
Ponownie czytając to, nie zgadzam się z tym const stringi static readonly stringrobię to samo. Wartości stałych są podstawiane w połączonym kodzie, podczas gdy do statycznych wartości tylko do odczytu odwoływane są. Jeśli masz constbibliotekę A, która jest używana przez bibliotekę B, biblioteka B zastąpi wszystkie odwołania do tej constzmiennej jej wartością dosłowną; gdyby static readonlyzamiast niej zmienna ta byłaby przywołana, a jej wartość ustalona w czasie wykonywania.
Jeff Yates,
3
Punkt Jeffa jest ważny podczas odwoływania się do bibliotek. Jeśli ponownie skompilujesz A i rozprowadzisz go ponownie , bez ponownej kompilacji B , B nadal będzie używać starych wartości.
Mark Sowul
5
String.Empty read only instead of a constant?
Jeśli uczynisz ciąg ciągiem stałym , kompilator zostanie zastąpiony ciągiem rzeczywistym wszędzie tam, gdzie go wywołasz, i wypełnisz kod tym samym ciągiem znaków po całym, a gdy kod zostanie uruchomiony, musisz również odczytywać ten ciąg znaków z innej pamięci dane.
Jeśli pozostawisz ciąg odczytywany tylko w jednym miejscu, tak jak to jest String.Empty, program utrzyma ten sam ciąg tylko w jednym miejscu i odczyta go lub odniesie się do niego - utrzymując dane w pamięci minimum.
Również jeśli skompilujesz dowolną bibliotekę DLL przy użyciu String.Empty jako const, i z jakiegokolwiek powodu zmieni się String.Empty, wówczas skompilowana biblioteka dll nie będzie działać tak samo, ponieważ costsprawi, że wewnętrzny kod faktycznie zachowa kopię łańcucha przy każdym połączeniu.
publicclassOneName{// note that the const exist also here !privateconststring cConst ="constant string";privatereadonlystring cReadOnly;privatestaticstring cStatic;staticOneName(){
cStatic ="static string";}publicOneName(){this.cReadOnly ="read only string";}protectedvoidFun(){string cAddThemAll ;// look here, will replace the const string everywhere is finds it.
cAddThemAll ="constant string";
cAddThemAll = cStatic;// but the read only will only get it from "one place".
cAddThemAll =this.cReadOnly;}}
Oznacza to, że ciąg const musi być zawsze tworzony w instancji klasy zawierającej tę const? Wydaje się, że wtedy znacznie lepiej jest używać statycznego odczytu tylko.
berserker
@theberserker dobrze jest lepszy, ale masz wszystkie opcje do użycia.
Aristos
> wtedy skompilowana biblioteka dll nie będzie działać tak samo, ponieważ koszt powoduje, że wewnętrzny kod faktycznie zachowuje kopię ciągu przy każdym wywołaniu. @Aristos To nie do końca prawda. Po skompilowaniu kodu, do „kopii” łańcucha będzie się odwoływać w bloku TEXT pliku wykonywalnego, a cały kod będzie po prostu odwoływał się do tego samego bloku pamięci. To, co zacytowałeś w drugim kroku, jest po prostu krokiem pośrednim.
Peter Dolkens
@ user1533523 dziękuję za notatkę - zrobię test, kiedy znajdę trochę czasu, aby to sprawdzić
Aristos
Skąd masz ten kod asemblera? C # nie kompiluje się w asemblerze!
jv110
0
Ta odpowiedź istnieje dla celów historycznych.
Pierwotnie:
Ponieważ Stringjest klasą i dlatego nie może być stałą.
Rozszerzona dyskusja:
Podczas weryfikacji tej odpowiedzi opracowano wiele przydatnych okien dialogowych, a zamiast jej usuwać, treść jest odtwarzana bezpośrednio:
W .NET, (w przeciwieństwie do Java) ciąg i Ciąg są dokładnie takie same. I tak, możesz mieć stałe literału ciągów w .NET - DrJokepu 3 lutego 09 o 16:57
Czy mówisz, że klasa nie może mieć stałych? - StingyJack 3 lutego 09 o 16:58
Tak, obiekty muszą używać tylko do odczytu. Tylko struktury mogą wykonywać stałe. Myślę, że kiedy użyjesz stringzamiast Stringkompilatora, zmieni const w readonly dla ciebie. Wszystko po to, by zadowolić programistów C. - Garry Shutler 3 lutego 09 o 16:59
tvanfosson właśnie wyjaśnił to trochę bardziej gadatliwie. „X nie może być stały, ponieważ zawierająca Y jest klasą” była po prostu zbyt bezkontekstowa;) - Leonidas 3 lutego 09 '17:01
string.Empty jest właściwością statyczną, która zwraca instancję klasy String, a mianowicie pusty ciąg, a nie samą klasę string. - tvanfosson 3 lutego 09 o 17:01
Empty jest instancją tylko do odczytu (nie jest własnością) klasy String. - senfo 3 lutego 09 o 17:02
Ból głowy Nadal uważam, że mam rację, ale teraz jestem mniej pewny. Badania wymagane dziś wieczorem! - Garry Shutler 3 lutego 09 o 17:07
Pusty ciąg jest instancją klasy ciągu. Puste jest polem statycznym (nie właściwością, stoję poprawionym) w klasie String. Zasadniczo różnica między wskaźnikiem a rzeczą, na którą wskazuje. Gdyby nie było tylko do odczytu, moglibyśmy zmienić, do której instancji odnosi się pole Puste. - tvanfosson 3 lutego 09 o 17:07
Garry, nie musisz przeprowadzać żadnych badań. Pomyśl o tym. Łańcuch jest klasą. Puste jest wystąpieniem ciągu. - senfo 3 lutego 09 o 17:12
Jest coś, czego nie do końca rozumiem: jak, u licha, statyczny konstruktor klasy String może utworzyć instancję klasy String? Czy to nie jest scenariusz „kurczaka lub jajka”? - DrJokepu 3 lutego 09 o 17:12 5
Ta odpowiedź byłaby poprawna dla prawie każdej innej klasy oprócz System.String. .NET ma dużo specjalnej obudowy dla ciągów, a jedną z nich jest to, że MOŻESZ mieć stałe ciągów, po prostu spróbuj. W tym przypadku Jeff Yates ma poprawną odpowiedź. - Joel Mueller 3 lutego 09 o 19:25
Jak opisano w §7.18, wyrażenie stałe jest wyrażeniem, które można w pełni ocenić podczas kompilacji. Ponieważ jedynym sposobem utworzenia wartości innej niż null typu referencyjnego innego niż ciąg znaków jest zastosowanie nowego operatora, a ponieważ nowy operator nie jest dozwolony w wyrażeniu stałym, jedyna możliwa wartość dla stałych typów referencyjnych inny niż string jest pusty. Poprzednie dwa komentarze zostały zaczerpnięte bezpośrednio ze specyfikacji języka C # i powtórzą to, o czym wspomniał Joel Mueller. - senfo 4 lutego 09 o 15:05 5
Głosuj poprawną odpowiedź. Jeśli przejdziesz do definicji, przekonasz się, że znajduje się ona w klasie String i jest instancją klasy String. Fakt, że jest wyświetlany jako małe litery, jest magią kompilatora.
Garry Shutler
To nie ja cię oceniłem, ale w .NET, (w przeciwieństwie do Java) ciąg i String są dokładnie takie same. I tak, możesz mieć stałe literału ciągów w .NET
Tamas Czinege
10
Ta odpowiedź byłaby poprawna dla prawie każdej innej klasy oprócz System.String. .NET ma dużo specjalnej obudowy dla ciągów, a jedną z nich jest to, że MOŻESZ mieć stałe ciągów, po prostu spróbuj. W tym przypadku Jeff Yates ma poprawną odpowiedź.
Joel Mueller
7
Prawie usunąłem tę odpowiedź, ponieważ pojawiła się znacznie lepsza, ale dyskusja w tych komentarzach jest warta kontynuacji.
Garry Shutler
1
@Garry, masz szczęście, że przeczytałem twój ostatni komentarz, w przeciwnym razie również głosuję. Łańcuch ma specjalną cechę w .NET, więc zdarzenie, które jest klasą referencyjną, może być stałą.
Odpowiedzi:
Powodem
static readonly
użycia zamiast tegoconst
jest użycie niezarządzanego kodu, jak wskazał Microsoft tutaj w wersji Shared Source Common Language Infrastructure 2.0 . Plik do obejrzenia tosscli20\clr\src\bcl\system\string.cs
.Znalazłem te informacje z tego przydatnego artykułu w CodeProject .
źródło
String.Empty
już tylko z tego powodu.Myślę, że jest tu wiele zamieszania i złych odpowiedzi.
Przede wszystkim
const
pola sąstatic
członkami ( nie członkami instancji ).Sprawdź rozdział 10.4 Stałe specyfikacji języka C #.
Jeśli
public const
członkowie są statyczni, nie można uznać, że stała utworzy nowy Obiekt.Biorąc to pod uwagę, poniższe wiersze kodu robią dokładnie to samo w odniesieniu do tworzenia nowego obiektu.
Oto uwaga od Microsoft, która wyjaśnia różnicę między 2:
Uważam więc, że jedyną możliwą odpowiedzią jest odpowiedź Jeffa Yatesa.
źródło
const string
istatic readonly string
robię to samo. Wartości stałych są podstawiane w połączonym kodzie, podczas gdy do statycznych wartości tylko do odczytu odwoływane są. Jeśli maszconst
bibliotekę A, która jest używana przez bibliotekę B, biblioteka B zastąpi wszystkie odwołania do tejconst
zmiennej jej wartością dosłowną; gdybystatic readonly
zamiast niej zmienna ta byłaby przywołana, a jej wartość ustalona w czasie wykonywania.Jeśli uczynisz ciąg ciągiem stałym , kompilator zostanie zastąpiony ciągiem rzeczywistym wszędzie tam, gdzie go wywołasz, i wypełnisz kod tym samym ciągiem znaków po całym, a gdy kod zostanie uruchomiony, musisz również odczytywać ten ciąg znaków z innej pamięci dane.
Jeśli pozostawisz ciąg odczytywany tylko w jednym miejscu, tak jak to jest
String.Empty
, program utrzyma ten sam ciąg tylko w jednym miejscu i odczyta go lub odniesie się do niego - utrzymując dane w pamięci minimum.Również jeśli skompilujesz dowolną bibliotekę DLL przy użyciu String.Empty jako const, i z jakiegokolwiek powodu zmieni się String.Empty, wówczas skompilowana biblioteka dll nie będzie działać tak samo, ponieważ
cost
sprawi, że wewnętrzny kod faktycznie zachowa kopię łańcucha przy każdym połączeniu.Zobacz ten kod na przykład:
przyjdzie przez kompilator jako:
i wezwanie do zgromadzenia
Edycja: poprawiona literówka
źródło
Ta odpowiedź istnieje dla celów historycznych.
Pierwotnie:
Ponieważ
String
jest klasą i dlatego nie może być stałą.Rozszerzona dyskusja:
Podczas weryfikacji tej odpowiedzi opracowano wiele przydatnych okien dialogowych, a zamiast jej usuwać, treść jest odtwarzana bezpośrednio:
źródło