"Static readonly" vs. "const"

Czytałem o polach const i static readonly. Mamy kilka klas, które zawierają tylko stałe wartości. Są one używane do różnych rzeczy w naszym systemie. Więc zastanawiam się, czy moje spostrzeżenie jest poprawne:

Czy tego rodzaju stałe wartości zawsze powinny być static readonly dla wszystkiego, co jest publiczne? I używać tylko const dla wewnętrznych/chronionych/prywatnych wartości?

Co polecacie? Czy powinienem w ogóle nie używać pól static readonly, ale raczej używać właściwości?
 1452
Author: Peter Mortensen, 2009-04-16

18 answers

public static readonly pola są nieco nietypowe; właściwości public static (tylko z get) byłyby bardziej powszechne (być może wspierane przez pole private static readonly).

const wartości są wypalane bezpośrednio w miejscu wywołania; jest to obosieczne:

  • jest bezużyteczne, jeśli wartość jest pobierana w trybie runtime, być może z config
  • jeśli zmienisz wartość const, musisz przebudować wszystkich klientów
  • ale może być szybszy, ponieważ unika wywołania metody...
  • ...które czasami mogą w każdym razie nie było to możliwe.]}

Jeśli wartość nigdy nie zmieni się , to const jest w porządku - Zero itp. robią rozsądne const ;P poza tym, static właściwości są bardziej powszechne.

 977
Author: Marc Gravell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-24 04:58:30

Użyłbym static readonly, Jeśli konsument jest w innym zespole. Posiadanie constI konsumenta w dwóch różnych zespołach jest dobrym sposobem, abystrzelić sobie w stopę .

 250
Author: Michael Stum,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-25 16:50:58

Kilka bardziej istotnych rzeczy do odnotowania:

Const int a

  • musi zostać zainicjowana.
  • inicjalizacja musi być w czasie kompilacji .

Readonly int a

  • może używać wartości domyślnej bez inicjalizacji.
  • inicjalizacja może być wykonana w Czas wykonania (Edit: tylko w konstruktorze).
 209
Author: Peter,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-25 12:05:56

To tylko uzupełnienie do innych odpowiedzi. Nie będę ich powtarzał (teraz cztery lata później).

Są sytuacje, w których a const i a non-const mają różne semantyki. Na przykład:

const int y = 42;

static void Main()
{
  short x = 42;
  Console.WriteLine(x.Equals(y));
}

Wypisuje True, natomiast:

static readonly int y = 42;

static void Main()
{
  short x = 42;
  Console.WriteLine(x.Equals(y));
}

Pisze False.

Powodem jest to, że metoda x.Equals ma dwa przeciążenia, jeden, który bierze w short (System.Int16) i taki, który bierze object (System.Object). Teraz pytanie brzmi, czy jeden lub oba stosuje się z moim y kłótnia.

Gdy y jest stałą czasu kompilacji (literalną), przypadek const, ważne staje się, że istnieje konwersja implicit Z int na short pod warunkiem, że int jest stałą i pod warunkiem, że kompilator C# weryfikuje, czy jego wartość mieści się w zakresie short (który 42 jest). Zobacz Implicit constant expression conversions w specyfikacji języka C#. Więc oba przeciążenia muszą być brane pod uwagę. Przeciążenie Equals(short) jest preferowane (dowolne short jest object, ale nie wszystkie objectshort). Tak więc y jest konwertowane na short, a to przeciążenie jest używane. Następnie Equals porównuje dwa short o identycznej wartości, co daje true.

Gdy y nie jest stałą, nie istniejeniejawna konwersja z int do short. To dlatego, że ogólnie int może być zbyt duży, aby zmieścić się w short. (An explicit konwersja istnieje, ale nie powiedziałem Equals((short)y), więc to nie ma znaczenia.) Widzimy, że stosuje się tylko jedno przeciążenie, Equals(object) jedno. Więc {[10] } jest spakowane do object. Następnie Equals porównuje System.Int16 do System.Int32, a ponieważ typy run-time nawet się nie zgadzają, to daje false.

Wnioskujemy, że w niektórych (rzadkich) przypadkach zmiana elementu typu const na pole typu static readonly (lub w inny sposób, gdy jest to możliwe) może zmienić zachowanie programu.

 188
Author: Jeppe Stig Nielsen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-09-13 13:30:01

Należy zauważyć, że const jest ograniczony do typów prymitywnych / wartości(wyjątkiem są łańcuchy).

 91
Author: Chris S,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-25 12:05:39

Tylko Do Odczytu Statycznego :

Wartość można zmienić za pomocą konstruktora static w czasie wykonywania. Ale nie poprzez funkcję członka.

Stała :

Domyślnie static. Wartość nie może być zmieniana z dowolnego miejsca (konstruktor, funkcja, runtime, itd. nigdzie).

Tylko Do Odczytu :

Wartość może być zmieniana przez konstruktor w czasie wykonywania. Ale nie poprzez funkcję członka.

Możesz zajrzeć do mojego repozytorium: C# property typy .

 31
Author: Yeasin Abedin Siam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-25 12:15:04

Słowo kluczowe readonly różni się od słowa kluczowego const. Pole const może być inicjowane tylko w deklaracji pola. Pole readonly może być zainicjalizowane w deklaracji lub w konstruktorze. Dlatego pola readonly mogą mieć różne wartości w zależności od użytego konstruktora. Ponadto, podczas gdy pole const jest stałą czasu kompilacji, pole readonly może być używane dla stałych runtime

Krótkie i przejrzyste odniesienie do MSDN tutaj

 27
Author: yazanpro,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-11-14 18:58:37

const i readonly są podobne, ale nie są dokładnie takie same.

A const jest stałą czasu kompilacji, co oznacza, że wartość ta może być obliczona w czasie kompilacji. Pole readonly umożliwia dodatkowe scenariusze, w których część kodu musi być uruchomiona podczas budowy typu. Po zbudowaniu pole readonly nie może zostać zmienione.

Na przykład, const Członkowie mogą być używane do definiowania członków takich jak:

struct Test
{
    public const double Pi = 3.14;
    public const int Zero = 0;
}

Ponieważ wartości takie jak 3.14 i 0 są stałymi czasu kompilacji. Rozważ jednak przypadek, w którym zdefiniujesz typ i chcesz podać kilka jego początkowych wystąpień. Na przykład możesz zdefiniować klasę kolorów i podać "stałe" dla popularnych kolorów, takich jak czarny, biały itp. Nie można tego zrobić z elementami const, ponieważ prawa strona nie jest stała czasu kompilacji. Można to zrobić ze zwykłymi statycznymi członkami:

public class Color
{
    public static Color Black = new Color(0, 0, 0);
    public static Color White = new Color(255, 255, 255);
    public static Color Red   = new Color(255, 0, 0);
    public static Color Green = new Color(0, 255, 0);
    public static Color Blue  = new Color(0, 0, 255);
    private byte red, green, blue;

    public Color(byte r, byte g, byte b) => (red, green, blue) = (r, g, b);
}

Ale wtedy nie ma nic, co powstrzyma klienta koloru od mucking z nim, być może poprzez zamianę Czarno-biały wartości. Nie trzeba dodawać, że spowodowałoby to konsternację dla innych klientów klasy kolorów. Funkcja "readonly" odnosi się do tego scenariusza.

Po prostu wprowadzając słowo kluczowe readonly w deklaracjach, zachowujemy elastyczną inicjalizację, jednocześnie zapobiegając blokowaniu kodu klienta.

public class Color
{
    public static readonly Color Black = new Color(0, 0, 0);
    public static readonly Color White = new Color(255, 255, 255);
    public static readonly Color Red   = new Color(255, 0, 0);
    public static readonly Color Green = new Color(0, 255, 0);
    public static readonly Color Blue  = new Color(0, 0, 255);
    private byte red, green, blue;

    public Color(byte r, byte g, byte b) => (red, green, blue) = (r, g, b);
}

Warto zauważyć, że członkowie const są zawsze statyczne, podczas gdy członkowie readonly mogą być statyczne lub nie, tak jak zwykłe pole.

Jest możliwe jest użycie jednego słowa kluczowego do tych dwóch celów, ale prowadzi to do problemów z wersjonowaniem lub problemów z wydajnością. Załóżmy przez chwilę, że użyliśmy jednego słowa kluczowego dla tego (const) i programista napisał:

public class A
{
    public static const C = 0;
}

I inny programista napisał kod, który opierał się na:

public class B
{
    static void Main() => Console.WriteLine(A.C);
}

Czy wygenerowany kod może polegać na tym, że A. C jest stałą czasu kompilacji? Czyli czy użycie A. C można po prostu zastąpić wartością 0? Jeśli powiesz " Tak " temu, wtedy to oznacza to, że deweloper A nie może zmienić sposobu inicjowania A. C.-wiąże To ręce dewelopera a bez pozwolenia.

Jeśli powiesz " nie " na to pytanie, pominięcie ważnej optymalizacji. Być może autor A jest pozytywny, że A. C zawsze będzie zerem. Użycie const i readonly pozwala twórcy a określić intencję. Zapewnia to lepsze zachowanie wersjonowania, a także lepszą wydajność.

 16
Author: Ramesh Rajendran,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-24 05:01:48

Preferuję używać const Kiedy tylko mogę, co, jak wspomniano w poprzednich odpowiedziach, ogranicza się do dosłownych wyrażeń lub czegoś, co nie wymaga oceny.

Jeśli przekroczę to ograniczenie, to wycofam się do Tylko do odczytu statycznego , z jednym zastrzeżeniem. Generalnie używałbym public static property Z getterem i zapleczem private static readonly , Jak wspomina Marc tutaj .

 12
Author: Peter Meyer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-25 12:06:51

Statyczne pole readonly jest korzystne przy wystawianiu na inne złożenia wartość, która może ulec zmianie w późniejszej wersji.

Na przykład, załóżmy, że zbiór X wyświetla stałą w następujący sposób:

public const decimal ProgramVersion = 2.3;

Jeśli assembly Y odwołuje się do X i używa tej stałej, wartość 2.3 zostanie upieczony do assembly Y podczas kompilacji. Oznacza to, że Jeśli X zostanie później skompilowana ze stałą ustawioną na 2.4, Y będzie nadal używaj starej wartości 2.3 do czasu rekompilacji Y. A static pole readonly pozwala uniknąć tego problemu.

Innym sposobem patrzenia na to jest to, że każda wartość, która może zmiana w przyszłości nie jest z definicji stała, więc powinna nie być reprezentowany jako jeden.

 7
Author: Yagnesh Cangi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-07 13:44:22

Const: Const jest niczym innym jak" stałą", zmienną, której wartość jest stała, ale w czasie kompilacji. I obowiązkowe jest przypisanie mu wartości. Domyślnie const jest statyczny i nie możemy zmienić wartości zmiennej const w całym programie.

Static ReadOnly: wartość zmiennej typu static Readonly może być przypisana w czasie wykonywania lub przypisana w czasie kompilacji i zmieniona w czasie wykonywania. Ale wartość tej zmiennej może być zmieniana tylko w statycznym konstruktor. I nie można go dalej zmieniać. Może zmienić się tylko raz w czasie wykonywania

Reference: c-sharpcorner

 7
Author: mayank,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-20 09:12:55

Istnieje niewielka różnica między polami const i static readonly w C#.Net

Const musi być zainicjalizowany wartością w czasie kompilacji.

Const jest domyślnie statyczny i musi zostać zainicjowany 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że być używany z DateTime datatype.

public const DateTime dt = DateTime.Today;  //throws compilation error
public const string Name = string.Empty;    //throws compilation error
public static readonly string Name = string.Empty; //No error, legal

Readonly może być zadeklarowane jako statyczne, ale nie jest to konieczne. Nie ma potrzeby inicjalizacji w momencie deklaracji. Its wartość może być przypisana lub zmieniona za pomocą konstruktora raz. Istnieje więc możliwość jednorazowej zmiany wartości pola readonly (nie ma znaczenia, czy jest statyczne czy nie), co nie jest możliwe przy const.

 4
Author: Chirag,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-07-02 11:35:14

Const:

  1. wartość powinna być podana przy deklaracji
  2. skompiluj stałą czasową

Readonly:

  1. wartość może być podana podczas deklaracji lub podczas wykonywania przy użyciu konstruktorów.Wartość może się różnić w zależności od użytego konstruktora.
  2. stała czasu pracy
 3
Author: dasumohan89,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-11 11:28:25

Const: stałe wartości zmiennych muszą być zdefiniowane wraz z deklaracją, a potem nie ulegną zmianie.const są domyślnie statyczne, więc bez tworzenia instancji klasy możemy uzyskać do nich dostęp. ma wartość w czasie kompilacji.

ReadOnly: możemy definiować wartości zmiennych tylko do odczytu podczas deklarowania, jak również przy użyciu konstruktora w czasie wykonywania. Zmienne tylko do odczytu nie mogą uzyskać dostępu bez instancji klasy.

Static readonly: możemy zdefiniować statyczne odczytywane tylko wartości zmiennych podczas deklarowania, jak również tylko przez statyczny konstruktor, ale nie z żadnym innym konstruktorem. Możemy również uzyskać dostęp do tych zmiennych bez tworzenia instancji klasy (jako zmienne statyczne).

Odczyt statyczny będzie lepszym wyborem, jeśli będziemy musieli używać zmiennych w różnych składach. Sprawdź pełne szczegóły w poniższym wpisie na blogu:

struny Const - bardzo wygodny sposób strzelania sobie w stopę

 3
Author: user1756922,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-25 12:20:20

Const (ustalany w czasie kompilacji) może być używany w przypadkach, gdy tylko statyczny odczyt nie może, jak w instrukcjach switch lub konstruktorach atrybutów. Dzieje się tak, ponieważ pola readonly są rozwiązywane tylko w czasie wykonywania, a niektóre konstrukcje kodu wymagają zapewnienia czasu kompilacji. W konstruktorze można obliczyć tylko statykę odczytu, co często jest istotną i użyteczną rzeczą. Różnica jest funkcjonalna, tak jak powinno być ich użycie moim zdaniem.

Pod względem alokacji pamięci, przynajmniej w przypadku ciągów (będących typem odniesienia), nie ma różnicy w tym, że oba są internowane i będą odwoływać się do jednej internowanej instancji.

Osobiście, moja wartość domyślna jest tylko statyczna, ponieważ ma dla mnie bardziej semantyczny i logiczny sens, zwłaszcza, że większość wartości nie jest potrzebna podczas kompilacji. A tak przy okazji, statyka public readonly nie jest niczym niezwykłym ani niezwykłym, jak stwierdza zaznaczona odpowiedź: na przykład System.String.Empty jest jedną.

 1
Author: DvS,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-11-18 15:27:22

Kolejną różnicą między deklarowaniem consti Tylko do odczytu statycznego jest alokacja pamięci.

Pole statyczne należy do typu obiektu, a nie do instancji tego typu. W rezultacie, gdy klasa zostanie odwołana po raz pierwszy, pole statyczne będzie " żyć " w pamięci przez resztę czasu, a ta sama instancja pola statycznego będzie odwoływana przez wszystkie instancje tego typu.

Natomiast pole const "należy do instancji tego typu.

Jeśli pamięć dealokacji jest dla Ciebie ważniejsza, użyj const . Jeśli prędkość, to użyj static readonly .

 0
Author: Boris Lipschitz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-01-21 06:45:57

Stałe są jak sama nazwa wskazuje, polami, które się nie zmieniają i są zwykle definiowane statycznie w czasie kompilacji w kodzie.

Zmienne tylko do odczytu są polami, które mogą się zmieniać w określonych warunkach.

Mogą być inicjalizowane, gdy po raz pierwszy zadeklarujesz je jako stałą, ale zazwyczaj są inicjowane podczas budowy obiektu wewnątrz konstruktora.

Nie można ich zmienić po zainicjowaniu, w warunkach wymienionych powyżej.

Statyczne tylko do odczytu brzmi jak kiepski wybór dla mnie, ponieważ, jeśli jest statyczne i nigdy się nie zmienia, więc po prostu użyj go public const. Jeśli może się zmienić, to nie jest stała i wtedy, w zależności od potrzeb, można użyć tylko do odczytu lub tylko zwykłą zmienną.

Kolejną ważną różnicą jest to, że stała należy do klasy, podczas gdy zmienna tylko do odczytu należy do instancji!

 0
Author: Claudiu Cojocaru,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-25 12:16:30

Jest jedno ważne pytanie, które nie jest nigdzie wspomniane w powyższych odpowiedziach i powinno skłonić cię do preferowania "const" szczególnie dla podstawowych typów ,takich jak" int"," string " itp.

Stałe mogą być używane jako parametry atrybutu , statyczne pole tylko do odczytu nie!

Usługa Azure functions HttpTrigger nie używa klasy HttpMethods w atrybucie

Jeśli tylko microsoft używał stałych dla HTTP GET, POST, DELETE itp.

Byłoby możliwe napisz

[HttpTrigger(AuthorizationLeve.Anonymous,  HttpMethods.Get)] // COMPILE ERROR: static readonly, 

Ale zamiast tego muszę uciekać się do

[HttpTrigger(AuthorizationLeve.Anonymous,  "GET")] // STRING

Lub użyć własnej stałej:

public class HttpConstants
{
    public const string Get = "GET";
}

[HttpTrigger(AuthorizationLeve.Anonymous,  HttpConstants.Get)] // Compile FINE!
 0
Author: UberFace,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-08-26 08:37:35