Best Practice: Avoid using const on read-only variables
April 22nd, 2008
I often mention the blindfold use of readonly and const keyword in C#. In general you can say that const variables get the value assigned at Compile time and are unchangeable once established. In opposite to that readonly variable get the value assigned at run time and are unchangeable once established.
A quick synopsis on the differences between ‘const’ and ‘readonly’:
const
- Can’t be static.
- Value is evaluated at compile time.
- Initiailized at declaration only.
readonly
- Can be either instance-level or static.
- Value is evaluated at run time.
- Can be initialized in declaration or by code in the constructor.
For a const thist would be typical:
public class MyClass { public const double PI = 3.14159; }
PI cannot be changed in the application anywhere else in the code as this will cause a compiler error.
Constants must be of an integral type (sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal, bool, or string), an enumeration, or a reference to null.
Constants can be marked as public, private, protected, internal, or protected internal.
As mentioned above a readonly can be assigned at run time. Due to that this is allowed:
public class MyClass { public readonly double PI; public MyClass() { PI = 3.14159; } }
—
A C# guideline defines that the best practise is to avoid const on read-only variables, therefor use the readonly keyword.
The reason why is very simple. Lets say you have the following code in a class library:
public class ServiceClass { public const int MyConst = 12; public readonly int MyReadOnlyVar = 10; }
And you have the following code in another assembly calling the code above.
ServiceClass service = new ServiceClass(); int someValue = ServiceClass.MyConst; someValue = service.MyReadOnlyVar;
You deploy both the class library and the assembly calling it. After deployment, a change is being made to the class library. you change the values of MyConst to 15 and MyReadOnlyVar to 15. You now release the class library and life is good. Is it?
What’s the values of someValue in the two statements below after the second release of the class library?
int someValue = ServiceClass.MyConst; someValue = service.MyReadOnlyVar;
Initially, when the compiler sees the line
int someValue = ServiceClass.MyConst;
it replaces ServiceClass.MyConst with 12.
At runtime the class library is not called for the value since it is a constant. As a result of this, the code calling into the class library is not aware that the value of ServiceClass.MyConst has changed. It will continue to use the old value 12 while the new value of MyConst is 15.





