fbpx
devstyle.pl - Blog dla każdego programisty
devstyle.pl - Blog dla każdego programisty
3 minut

“const” vs “static readonly”


06.06.2008

Składowe klasy, których niezmienności jesteśmy pewni, możemy oznaczyć przynajmniej dwojako:

 1:   public class ConstantValues
2: {
3: public const int Constant = 666;
4: public static readonly int StaticReadonly = 123;
5: }

Efekt ich wykorzystania jest taki sam – mamy dostęp do przypisanych im wartości spoza klasy, jednak nie możemy ich zmienić. Dokładne znaczenie: const to “wartość stała”, a static readonly to “składowa statyczna tylko do odczytu” Konstrukcje te jednak różnią się kilkoma szczegółami. Poniżej wymieniam parę, które aktualnie przyszły mi do głowy. Być może różnic jest więcej, ale i tak najważniejszą zostawiłem na koniec:

1. Składowa readonly może być zainicjowana przy deklaracji LUB w statycznym konstruktorze, ważne, aby miało to miejsce dokładnie jeden raz (czyli możemy przypisać wartość wyliczoną przez statyczną metodę). Z kolei składowa const musi być zainicjowana przy deklaracji za pomocą literału napisowego, liczby, bądź wartości boolowskiej.

2. Tylko składowe const mogą posłużyć jako argumenty w deklaracji użycia atrybutu, czyli to się skompiluje

 1:   [SomeAttribute(ConstantValues.Constant)]
2: void SomeMethod() { }

a to już nie:

 1:   [SomeAttribute(ConstantValues.StaticReadonly)]
2: void SomeMethod() { }

3. Najważniejsze: wartości const są podmieniane w czasie kompilacji, podczas gdy wartości static są pobierane podczas działania programu! Najpierw dowód, a potem uzasadnienie “dlaczego to takie ważne”:

 1:   int constant;
2: int staticReadonly;
3: void UseConstants()
4: {
5: constant = ConstantValues.Constant;
6: staticReadonly = ConstantValues.StaticReadonly;
7: }

Po skompilowaniu ciało powyższej metody przedstawia się w Reflectorze następująco:

 1:   private void UseConstants()
2: {
3: this.constant = 0x29a;
4: this.staticReadonly = ConstantValues.StaticReadonly;
5: }

I cóż się okazało? Zamiast ConstantValues.Constant mamy 0x29a, czyli nieświęte 666 w hexach, z pominięciem odwołania do klasy zawierającej tą wartość!
Dobra, “no i co z tego?”. Wyobraźmy sobie sytuację, gdy ten przygłupi prymitywny przykład jest częścią bardziej rozbudowanego systemu. Klasa ConstantValues znajduje się w ConstantAssembly.dll, natomiast wartości z niej są pobierane przez algorytmy w Algorithms.dll. W sytuacji, gdy chcemy zmienić wartość składowej ConstantValues.StaticReadonly wszystko jest ok – podmieniamy na co nam trzeba, kompilujemy ConstantAssembly.dll, wrzucamy nową wersję i wszystko śmiga. Co się jednak dzieje, gdy chcemy zmodyfikować ConstantValues.Constant? Podmiana ConstantAssembly.dll nic nie zmienia! Musimy przekompilować nie tylko ConstantAssembly, ale również wszystkie biblioteki z niej korzystające, ponieważ to właśnie podczas KOMPILACJI pobierane i podstawiane są te wartości! Dlatego też trzeba zdawać sobie sprawę z owej różnicy i świadomie stosować odpowiednie rozwiązania. Metodzie “chybił-trafił” mówimy stanowcze i zdecydowane NIE!

0 0 votes
Article Rating
1 Comment
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
sebcyg
15 years ago

Ciekawostkę jest też to, że wartość pól readonly jest jednak writeable… przy pomocy refleksji.

Kurs Gita

Zaawansowany frontend

Szkolenie z Testów

Szkolenie z baz danych

Książka

Zobacz również