Posted on Sunday September 6, 2009

Const vs Readonly in C#

Const

The value of your const property is set at compile time and can’t change at runtime. Where the const is used in the callee, this value is replaced by the compiler. This can lead to versioning problems if your const changes in later versions.

So if you have version 1 of a class library, and the constant value is “3”, and then you change this value in version 2 to “5”, you will get some unpredictable things happening, possibly breaking your code. The image below shows a class called Tester, that in version 1 had CONST_B as “3” then in version 2 changed this to “5”. It’s a crude example but you get an idea of how the compiler is using the field from the tooltip.

Constant readonly

Const can’t be marked as static - the keyword denotes they are static, unlike readonly fields which can.

They also can’t be anything except value (primitive) types, with the exception of strings. If you try to assign your const to something like:

public const System.Net.Cookie CONST_A = new System.Net.Cookie();

You get a semantic error from the compiler.

Readonly

The readonly keyword marks the field as unchangeable. However the property can be changed inside the constructor of the class. If the field is also static, then the same applies but inside the static constructor. This means the problems with versioning you get with the const keyword are removed, the value isn’t replaced by the compiler but rather a field exists with metadata.

The readonly only keyword can also be combined with static to make it act in the same way as a const (atleast on the surface). There is a marked difference when you look at the IL between the two. In the image below MYVALUE2 is static readonly, MYVALUE3 is readonly (no static), CONSTB is just marked as const.

Const readonly ildasm

You can see that const fields are marked as “literal” while readonly is “initonly”. Initonly is also a keyword in managed C++. In terms of memory management of the two, I assume that static ‘literals’ are stored on the stack with value types, being limited to value types only.

More detailed information can be found on here.