Monday, September 22, 2008

Const OR Static ReadOnly


When declaring a member which will hold a constant value, I have seen instances there are folks who use ‘const’ and also there are folks who loves to use ‘static readonly’. There are debates over it, which one is the correct way to follow … looking down inside(MSIL level ), here is what I found.
Let us consider, we are writing a Library and we have declared two variables in a public class as mentioned below …
public static readonly int ReadOnlyStatic = 100;
public const int ReadOnlyConst = 100;

Now let us create a Console Application which will have a reference of the above library, and in the Main method we write the following code block…
static void Main(string[] args)
{
int _staticReadonly = TestClass.ReadOnlyStatic;
int _const = TestClass.ReadOnlyConst;
Console.WriteLine("Constant:{0}, ReadOnlyStatic:{1}", _const, _staticReadonly);
If we do ILDASM of the codeblock, here is what we will found ….
.locals init ([0] int32 _staticReadonly,[1] int32 _const)
IL_0001: ldsfld int32 [POC_ConstantVsReadOnly]POC_ConstantVsReadOnly.TestClass::ReadOnlyStatic
IL_0006: stloc.0
IL_0007: ldc.i4.s 100
IL_0009: stloc.1
So, it’s clear from the MSIL that in case of const, the compiler assign(hardcode) the value into the variable( refer to the second underlined statement), and in case of static readonly it refers to the class member(refer to the first underlined statement).

What does that mean ? That means for some reason if we change the value of constant in the Library we have to recompile all the assemblies which have a reference to this library, however if we change the value of static readonly and then we would be fine if we just replace the compiled library in the referenced assemblies Bin folder.
To test this feature, let us do this:
A. Let us change the value in the Library as mentioned below and then compile the library.
public static readonly int ReadOnlyStatic = 50;
public const int ReadOnlyConst = 50;

B. Now manually replace the newly complied library in the console app Bin folder( I had set ‘copy local’ as true while having a reference of the library ) , let us run the console application( without compiling), now we will see the value of ‘const’ is 100 but the value of ‘static readonly’ as 50, now compile the Console app project, and this time both of the will show the value as 50.

So, we must remember if we declare a member as ‘const’ in a library, then upon changing the value all the dependent applications have a to release a new version just because the constant value has been changed.

What about performance ? Only on the first call, static readonly will be slower compare to const, the subsequent calls should be as good as const.