In our daily coding practices, we get options to declare variables as const or readonly. I never cared about the basic difference of these two, except that one needs to be assigned a value at compile time and the other at run time. But there is more to the difference between the two. Let's try to evaluate that difference.
const: the value of a const are assigned at compile time itself and once assigned, cannot be changed. They are static in nature and we cannot use the static keyword with them. They are also called compile-time constants, since their value must be set at the compile time itself.
readonly: the value of a readonly field can be set either when they are declared or can be assigned in the constructor of the class. They are also called run time constants since their values can be changed at run-time, but the point is that they can be only changed inside the constructor of the class.
As I mentioned, there is more to what these statements define, next we will try to discuss that. Let's start with an example. Suppose we have a class library, say SampleClass.cs, with two integer type variables a and b, declared in it. Here, a is of type const and b is of type readonly. Now we assign values to these variables as:
public const Int32 ConstInteger = 333;
public readonly Int32 ReadOnlyInteger = 666;
Next, we build the class library and add its DLL to our client project and deploy the project on the client machine. Now due to some requirement change, we need to change the value of ConstInteger to 444 and ReadOnlyInteger to 777. So we update the values of both the variables in the class library and replace the updated DLL on the client's machine. Then we check what the results are. A shocking one, the value for the ReadOnlyInteger changes but the ConstInteger remains the same.
Why it happened
The reason is that for any const type variable used in another assembly, the actual code must also be re-compiled to update the value of the const in the Intermediate Language (IL) of the code where it is being used. But this is not the case with the readonly. This was the reason that the changes for readonly were reflected but not for the const type. It is like the value of the const was embedded in the IL of the code where we used the class library reference (when we compiled the code). So in order to change the value of the const, we need to re-compile the code where it is being used, to update its value in the IL.
Let's try to check the behavior with a sample application. For this, we will create a class library having a class SampleClass, with two integer variables, one of type const and another of type readonly. Then build the project.
Next we add a console application. Then add a reference to the SampleClass.dll in this application and simply print these values. So our code is like the following:
Finally, we generate a setup or .exe file for it and install the setup file on our system. Open the location where we installed it and run the application. We can see the values are printed.
Now, change the values of these variable to new values. Let's say, change ConstInteger to 444 and ReadOnlyInteger to 777. This time, build the class library only and directly replace it's DLL on the location, where we installed the application. Now run the .exe application and see the results.
This time, the value of only ReadOnlyInteger is changed, for the same reason that we discussed above. So if we need to change the value of ConstInteger also, we need to re-build the console application also and then install it again. Try it and this time it will work.
The decision to choose between the two will matter the most in case we are providing service-based DLLs to the clients. It becomes a dependency that the consumer client must re-compile the code to ensure that the updated value of the const is updated in his code also. So this is the behavior I was referring to when I said that there is more to what the definitions of these variables mean.
I hope you enjoyed reading this.