In this article i shall be discussing about constants and read only fields which we all use in our .NET variant language codes viz C#, VB .NET, VC++, etc.
Constants are not changeable values in the entire code base once it is defined.
Lets dig a bit deeper into the const keyword which we use in our C# code. Basically, constants are by default/implicitly static for the scope in which it is defined. Also note that there wont be any memory created for the constants by the run time. So what happens under the hood, lets see via IL and a C# code.
As you can see from the above image, i have used a constant inside the main method. Now lets look at the IL (using ILSPY/ILDASM) to see if there is any memory created for the variable or not:
As you can see from the above image, the compiler didn’t create any OpCodes for
TCPPortNumber. Now lets change that variable to non-constant and see the IL:
As you can see from in the image, Line 10 block initializes the variable and in line 15 there is a stack memory being created for loading value 25. So this proves that there is no memory created for the constant variables.
Now, you might be wondering that, If no memory is created for constants then if i use that variable at some where down the line to do some operation, how or where the run time picks or finds the value.
Let me come back to the same code with constant usage, with a bit of modification as shown:
Since we are appending the constant value to the string, now the constant variable should get created on memory right? It looks like that logically atleast. So lets check the IL for the new code then:
As you can see, still the memory for the constant variable is not created by the compiler, but in the usage code the value is directly embedded into IL at line 16.
Another case is, If the constants are defined in another assembly say AssemblyA and their usages are in different assembly say AssemblyB, after compilation of both assemblies and before run time you can delete that AssemblyA which had all constants defined, from the disk and still your usage code runs. So this proves that, at the compilation stage itself the compiler embeds constant variable’s value every where its been used. So that the CLR wont lookout for the constant variable in memory to refer at run time.
So, as a developer you should be careful when your using constants. Assume, you have defined all constants in an assembly AssemblyA and your usage code is in AssemblyB. To make it more interesting, the AssemblyA is developed by a remote team. So when ever AssemblyA is compiled upon changes to constant values, the same value wont be reflected/embedded into your AssemblyB code usage by compiler (assuming no usage of strong named assemblies here). To solve this, both assemblies has to be build together upon any changes.
To overcome this problem, you can use readonly keyword in your production code. Here what happens is, a variable declared as readonly can be defined either at its declaration or in the constructors of the class so that the value for it is unique/known at the construction of the object itself. But you can bypass this rule via reflection.
So every time readonly variable is referred in the code, at run time CLR looks up for this variable and gets the value (loading an assembly if its defined there). Hence a memory is created for readonly variables.