Czytałem o const
i static readonly
pola. Mamy pewne klasy, które zawierają tylko wartości stałe. Używane do różnych rzeczy w naszym systemie. Zastanawiam się więc, czy moja obserwacja jest poprawna:
Czy tego rodzaju stałe wartości powinny zawsze dotyczyć static readonly
wszystkiego, co publiczne? I używać tylko const
do wewnętrznych / chronionych / prywatnych wartości?
Co polecasz? Czy może nie powinienem nawet używać static readonly
pól, a raczej używać właściwości?
static readonly
: spróbuj użyć stałej w środku,IEnumerator
która wyzwalałaby niemożliwy do sprawdzenia,yield
a dostaniesz przerażający „Wewnętrzny błąd kompilatora” . Nie testowałem kodu poza Unity3D, ale ufam, że jest to błąd mono lub .NET . Jest to jednak problem c # .static readonly
nie może być użyty wswitch-case
instrukcji jakocase
zmienna,const
jest wymagany do tego celu.static readonly
nie może być również użyty jako parametr atrybutuOdpowiedzi:
public static readonly
pola są trochę niezwykłe;public static
właściwości (tylko z aget
) byłyby bardziej powszechne (być może poparteprivate static readonly
polem).const
wartości są zapisywane bezpośrednio w witrynie wywołującej; to jest obosieczne:Jeśli wartość nigdy się nie zmieni, to const jest w porządku -
Zero
etc tworzy rozsądne const; p Poza tymstatic
właściwości są bardziej powszechne.źródło
readonly
pola nie mogą być używane w instrukcjach switch / case, zamiast tego trzebaconst
.Użyłbym,
static readonly
jeśli konsument jest w innym zespole. Posiadanie Konsumentaconst
i Konsumenta w dwóch różnych zespołach to dobry sposób na zastrzelenie się w stopę .źródło
internal const
lub wpublic static readonly
zależności od pożądanej widoczności.public const
(np. Jakiejkolwiek części standardu. Za każdym razem, gdy pracuję z XML, istnieje plik przestrzeni nazw z kilkomapublic const string
.) Ale ogólniepublic const
należy go używać tylko po odpowiednim rozważeniu konsekwencji.Należy zwrócić uwagę na kilka bardziej istotnych kwestii:
const int a
readonly int a
źródło
ctor
jedynego.To tylko uzupełnienie innych odpowiedzi. Nie powtórzę ich (teraz cztery lata później).
Są sytuacje, w których a
const
i non-const mają inną semantykę. Na przykład:drukuje
True
, natomiast:pisze
False
.Powodem jest to, że metoda
x.Equals
ma dwa przeciążenia, jeden przyjmującyshort
(System.Int16
) i drugi przyjmującyobject
(System.Object
). Teraz pytanie brzmi, czy jedno lub oba dotyczą mojegoy
argumentu.Gdy
y
jest stałą czasową kompilacji (dosłowną), w tymconst
przypadku staje się ważne, że istnieje niejawna konwersja zint
nashort
pod warunkiem, żeint
jest ona stała, i pod warunkiem, że kompilator C # zweryfikuje, czy jego wartość mieści się w zakresieshort
( który42
jest). Zobacz Implikowane konwersje wyrażeń stałych w specyfikacji języka C #. Dlatego należy wziąć pod uwagę oba przeciążenia. PrzeciążenieEquals(short)
jest preferowane (każdyshort
jestobject
, ale nie wszystkieobject
sąshort
). Taky
jest konwertowane nashort
i używane jest przeciążenie. NastępnieEquals
porównuje dwashort
o identycznej wartości, a to dajetrue
.Gdy
y
nie jest stałą, nie istnieje niejawna konwersja zint
nashort
. To dlatego, że ogólnie rzecz biorącint
może być zbyt duże, aby zmieściło się wshort
. (Istnieje wyraźna konwersja, ale nie powiedziałemEquals((short)y)
, więc to nie ma znaczenia.) Widzimy, że ma zastosowanie tylko jedno przeciążenie,Equals(object)
jedno. Więcy
jest zapakowane wobject
. NastępnieEquals
porównamy aSystem.Int16
do aSystem.Int32
, a ponieważ typy wykonawcze nawet się nie zgadzają, to dafalse
.Dochodzimy do wniosku, że w niektórych (rzadkich) przypadkach zmiana elementu
const
typu nastatic readonly
pole (lub w inny sposób, gdy jest to możliwe) może zmienić zachowanie programu.źródło
short x = 42;
legalne. Ponieważ maszint
, mianowicie dosłowny42
, który domyślnie zamienia się wshort x
. Ale mogliby ograniczyć to tylko do literałów liczbowych; zdecydowali się jednak zezwolić na takie rzeczy, jakshort x = y;
gdziey
jest zdefiniowany jakoconst int y = 42;
, a potem skończyli z tym.Należy zauważyć, że const jest ograniczony do typów pierwotnych / wartości (wyjątek stanowią ciągi znaków)
źródło
const
można go używać także do innych typów, z tym wyjątkiem, że należy go zainicjować na wartość null, co czyni go bezużytecznym :)System.Exception
? :)const
można stosować, sąsbyte
,byte
,short
,ushort
,int
,uint
,long
,ulong
,char
,float
,double
,decimal
,bool
, plus wszelkieenum
rodzaje.const
nie można użyć dla innych typów wartości, takich jakDateTime
lubTimeSpan
lubBigInteger
. Nie można go również użyć doIntPtr
struktury (przez niektórych uważany za „prymitywny”; termin typ prymitywny jest mylący w języku C #). ↵↵const
Można stosować dla wszystkich typów referencji . Jeśli typ jeststring
, można podać dowolną wartość ciągu. W przeciwnym razie wartość musi wynosićnull
.const
za pomocądefault
. W przypadkustruct
typów jest to instancja ze wszystkimi członkami ustawionymi na wartości domyślne.Statyczny tylko do odczytu : Wartość można zmienić za pomocą
static
konstruktora w czasie wykonywania. Ale nie poprzez funkcję członka.Stała : domyślnie
static
. Wartości nie można zmienić z dowolnego miejsca (Ctor, funkcja, środowisko uruchomieniowe itp. Nigdzie).Tylko do odczytu : Wartość można zmienić za pomocą konstruktora w czasie wykonywania. Ale nie poprzez funkcję członka.
Możesz zobaczyć moje typy repozytoriów: C # .
źródło
Słowo
readonly
kluczowe różni się odconst
słowa kluczowego.const
Pole może zostać zainicjowany wyłącznie w deklaracji pola.readonly
Pole może być zainicjowana albo w deklaracji lub w konstruktorze. Dlategoreadonly
pola mogą mieć różne wartości w zależności od zastosowanego konstruktora. Ponadto, chociażconst
pole jest stałą czasową kompilacji,readonly
pole może być używane do stałych środowiska wykonawczegoKrótkie i jasne odniesienie do MSDN tutaj
źródło
const
ireadonly
są podobne, ale nie są dokładnie takie same.const
Pole jest stałą czasu kompilacji, co oznacza, że wartość ta może być obliczana w czasie kompilacji.readonly
Pole umożliwia dodatkowe scenariusze, w których należy przeprowadzić kilka kod podczas budowy tego typu. Po zakończeniu budowyreadonly
pola nie można zmienić.Na przykład
const
członków można używać do definiowania członków, takich jak:Ponieważ wartości takie jak 3.14 i 0 są stałymi czasów kompilacji. Rozważ jednak przypadek, w którym definiujesz typ i chcesz podać niektóre jego wcześniejsze wersje. Na przykład, możesz chcieć zdefiniować klasę Kolor i podać „stałe” dla typowych kolorów, takich jak Czarny, Biały itp. Nie można tego zrobić z elementami stałymi, ponieważ prawa strona nie jest stała czasu kompilacji. Można to zrobić za pomocą zwykłych elementów statycznych:
Ale nie ma nic, co powstrzymałoby klienta Color od zepsucia się nim, być może poprzez zamianę wartości czerni i bieli. Nie trzeba dodawać, że spowodowałoby to konsternację u innych klientów klasy Color. Funkcja „tylko do odczytu” rozwiązuje ten scenariusz.
Po prostu wprowadzając
readonly
słowo kluczowe w deklaracjach, zachowujemy elastyczną inicjalizację, jednocześnie zapobiegając pomijaniu kodu klienta.Warto zauważyć, że stałe elementy są zawsze statyczne, podczas gdy element tylko do odczytu może być statyczny lub nie, tak jak zwykłe pole.
Możliwe jest użycie jednego słowa kluczowego do tych dwóch celów, ale prowadzi to do problemów z wersją lub problemów z wydajnością. Załóżmy przez chwilę, że użyliśmy do tego jednego słowa kluczowego (const), a programista napisał:
a inny programista napisał kod, który polegał na A:
Czy generowany kod może polegać na tym, że AC jest stałą czasową kompilacji? Czyli użycie AC można po prostu zastąpić wartością 0? Jeśli powiesz „tak”, oznacza to, że twórca A nie może zmienić sposobu inicjalizacji AC - wiąże to ręce twórcy A bez pozwolenia.
Jeśli powiesz „nie” w tym pytaniu, ważna optymalizacja zostanie pominięta. Być może autor A jest przekonany, że AC zawsze będzie wynosić zero. Użycie zarówno const, jak i readonly pozwala twórcy A określić intencję. To zapewnia lepsze zachowanie wersjonowania, a także lepszą wydajność.
źródło
Wolę używać const, kiedy tylko mogę, co, jak wspomniano powyżej, ogranicza się do dosłownych wyrażeń lub czegoś, co nie wymaga oceny.
Jeśli dojdę do tego ograniczenia, powrócę do statycznego odczytu tylko z jednym zastrzeżeniem. Na ogół używałbym publicznej własności statycznej z geterem i prywatnym statycznym polem tylko do odczytu, jak wspomina tutaj Marc .
źródło
Odniesienie: c-sharpcorner
źródło
Statyczne pole tylko do odczytu jest korzystne, gdy udostępnia się innym zestawom wartość, która może ulec zmianie w późniejszej wersji.
Załóżmy na przykład, że zespół
X
odsłania stałą w następujący sposób:Jeśli zestaw
Y
odwołuje sięX
i używa tej stałej, wartość 2.3 zostanie upieczona w zestawieY
po skompilowaniu. Oznacza to, że jeśliX
później zostanie ponownie skompilowany ze stałą ustawioną na 2.4,Y
nadal będzie używać starej wartości 2.3, aż doY
ponownej kompilacji. Statyczne pole tylko do odczytu pozwala uniknąć tego problemu.Innym sposobem patrzenia na to jest to, że jakakolwiek wartość, która może się zmienić w przyszłości, nie jest stała z definicji i dlatego nie powinna być reprezentowana jako jedna.
źródło
const:
tylko czytać:
źródło
Const : const wartości zmiennych muszą zostać zdefiniowane wraz z deklaracją, a następnie nie ulegną zmianie. const są domyślnie statyczne, więc bez tworzenia instancji klasy możemy uzyskać do nich dostęp. ma to wartość w czasie kompilacji
ReadOnly : tylko zmienne wartości, które możemy zdefiniować podczas deklarowania, a także przy użyciu konstruktora w czasie wykonywania. Zmienne tylko do odczytu nie mogą uzyskać dostępu bez wystąpienia klasy.
Statyczny tylko do odczytu : statyczne wartości tylko do odczytu, które możemy zdefiniować podczas deklarowania, a także tylko za pomocą konstruktora statycznego, ale nie za pomocą żadnego innego konstruktora. Do tych zmiennych możemy również uzyskać dostęp bez tworzenia instancji klasy (jako zmienne statyczne).
statyczny tylko do odczytu będzie lepszym wyborem, jeśli będziemy musieli wykorzystywać zmienne w różnych zestawach. Sprawdź pełne szczegóły w poniższym linku
https://www.stum.de/2009/01/14/const-strings-a-very-convenient-way-to-shoot-yourself-in-the-foot/
źródło
Istnieje niewielka różnica między stałymi a statycznymi polami tylko do odczytu w języku C # .Net
const musi być zainicjowany wartością w czasie kompilacji.
const jest domyślnie statyczny i musi być inicjalizowany ze stałą wartością, której nie można później modyfikować. Nie można go używać ze wszystkimi typami danych. Dla ex-DateTime. Nie można go używać z typem danych DateTime.
tylko do odczytu można zadeklarować jako statyczne, ale nie konieczne. Nie ma potrzeby inicjowania w momencie deklaracji. Jego wartość można przypisać lub zmienić za pomocą konstruktora jeden raz. Istnieje więc możliwość jednorazowej zmiany wartości pola tylko do odczytu (nie ma znaczenia, czy jest ono statyczne, czy nie), co nie jest możliwe w przypadku const.
źródło
Stałe są jak sama nazwa wskazuje, pola, które się nie zmieniają i zwykle są definiowane statycznie w czasie kompilacji w kodzie.
Zmienne tylko do odczytu to pola, które mogą się zmieniać w określonych warunkach.
Można je zainicjować, gdy zadeklarujesz je po raz pierwszy jako stałą, ale zwykle są one inicjowane podczas budowy obiektu wewnątrz konstruktora.
Nie można ich zmienić po inicjalizacji w wyżej wymienionych warunkach.
Statyczny tryb „tylko do odczytu” wydaje mi się złym wyborem, ponieważ jeśli jest statyczny i nigdy się nie zmienia, więc użyj go jako const, jeśli może się zmienić, to nie jest stały, a następnie, w zależności od potrzeb, możesz użyć odczytu -tylko lub tylko zmienna regularna.
Kolejnym ważnym rozróżnieniem jest to, że stała należy do klasy, a zmienna tylko do odczytu należy do instancji!
źródło
Stała (określana w czasie kompilacji) może być używana w przypadkach, w których statyczny tylko do odczytu nie może, na przykład w instrukcjach switch lub konstruktorach atrybutów. Jest tak, ponieważ pola tylko do odczytu są rozwiązywane tylko w czasie wykonywania, a niektóre konstrukcje kodu wymagają zapewnienia czasu kompilacji. Tylko konstruktor może być obliczony w konstruktorze, co często jest istotną i przydatną rzeczą. Różnica jest funkcjonalna, tak jak moim zdaniem powinno być ich użycie.
Pod względem alokacji pamięci, przynajmniej w przypadku łańcuchów znaków (będących typem odniesienia), wydaje się, że nie ma różnicy w tym, że oba są internowane i będą odwoływały się do jednej internowanej instancji.
Osobiście mój domyślny jest tylko statyczny, ponieważ ma dla mnie bardziej semantyczny i logiczny sens, zwłaszcza, że większość wartości nie jest potrzebna w czasie kompilacji. Nawiasem mówiąc, publiczna statystyka tylko do odczytu nie jest niczym niezwykłym ani niczym niezwykłym, jak zaznaczono w zaznaczonej odpowiedzi: na przykład
System.String.Empty
jest jedna.źródło
Inną różnicą między deklarowaniem const a statycznym tylko do odczytu jest przydział pamięci.
Pole statyczne należy do typu obiektu, a nie do instancji tego typu. W rezultacie, po odwołaniu do klasy po raz pierwszy, pole statyczne „żyje” w pamięci przez resztę czasu, a do tego samego wystąpienia pola statycznego będą się odnosić wszystkie instancje tego typu.
Z drugiej strony stałe pole „należy do instancji typu.
Jeśli ważniejsza jest dla ciebie pamięć delokalizacji, wolisz użyć const . Jeśli prędkość, użyj statycznego tylko do odczytu .
źródło