Kilka postów wcześniej pisałem o różnicach między const a read-only. Dzisiaj chciałbym pokazać scenariusz, który pokazuje kiedy NIE używać słowa const. Const jest doskonałym rozwiązaniem dla liczb, które są po prostu ZAWSZE stałe. Przykład? Liczba PI ma jedną wartość i oczywiście nigdy się nie zmieni.
Istnieją jednak przypadki gdzie liczby w kodzie są zastępowane stałymi co nie zawsze jest dobrym wzorcem. Załóżmy, że mamy klasę przechowującą pewne parametry algorytmu:
namespace ClassLibrary1 { public class Consts { public const int N = 10; } }
Proszę zauważyć, że klasa jest zlokalizowana w osobnej bibliotece. Następnie w innej aplikacji musimy wykorzystać taką stałą:
namespace ConsoleApplication1 { class Program { static void Main(string[] args) { Console.WriteLine(Consts.N); } } }
Co prawda uniknęliśmy magic numbers ale niestety kod nie jest elastyczny. Jak wiemy, const nie alokuje pamięci a jest wstawiany w procesie kompilacji. Jeśli użytkownik biblioteki zmieni wartość N wtedy uruchomienie aplikacji nie wyświetli nowej wartości. Po prostu liczba jest wstawiana w czasie kompilacji i zawsze zarówno ClassLibrary1 jak i ConsoleApplication1 muszą zostać przekompilowane. Tak naprawdę N nie jest stałą (bo może ulec zmianie) a wartością tylko do odczytu i lepiej wykorzystać readonly:
public static class Consts { public static readonly int N = 55; }
Przy każdej modyfikacji N wystarczy tylko przekompilować ClassLibrary1. Wniosek taki, że const lepiej używać dla symboli (które zawsze mają taką samą nazwę) a readonly dla wartości, które może modyfikować tylko autor. Oczywiście ma to znaczenie w aplikacjach modularnych a nie składających się z pojedynczej biblioteki. Często stałe są używane wyłącznie w jednej bibliotece i wtedy również nie ma problemu z wersjonowaniem ich.
Albo stosować “const” z modyfikatorem “private” w klasie lub “internal” w bibliotece. Wartości stałe są wstawiane “inline” w kodzie skompilowanym, który dzięki temu może być lepiej optymalizowany.
Natomiast w przypadku potrzeby publikowania ich wartości lepiej napisać metody (interfejsy), które je zwracają.