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.
Let's 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 won't be any memory created for the constants by the run time. So what happens under the hood, let's 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 let's 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 let's 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 somewhere 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 at least. So let's 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 everywhere it has been used. So that the CLR won't lookout for the constant variable in memory to refer at run time.
So, as a developer, you should be careful when you are 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 whenever AssemblyA
is compiled upon changes to constant values, the same value won't be reflected/embedded into your AssemblyB
code usage by compiler (assuming no usage of strong named assemblies here). To solve this, both assemblies have to be built 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.
Thanks for reading!