Click here to Skip to main content
Click here to Skip to main content

Tagged as

Go to top

Internals of Constants and Readonly

, 3 Oct 2011
Rate this:
Please Sign up or sign in to vote.
Indepth details about constants and readonly

Introduction

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.

Background

Constants are not changeable values in the entire code base once it is defined.

Description

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.

public static void Main(string[] args)
        {
            const int TCPPortNumber = 25;
        }

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 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:

public class Program
    {
        const int TCPPortNumber = 25;
        
        static void Main(string[] args)
        {
            string str = "TCP Port Number is : " + TCPPortNumber);
        }       
    }

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 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's 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 that 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 build together upon any changes.

So if you have 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.

Please note that you can't declare it in any of the methods or ctors  because, throughout your class instance life time, the readonly variable should be known and so its value. Hence it is declared in class scope and defined there itself or at object construction AKA ctor. But you can bypass this rule via reflection.

Let's dig a bit deep and see what is happening:

At line 12, the run time shall load the value of readOnlyVariable from memory.

So every time readonly variable is referred in the usage code, at run time CLR looks up for this variable and gets the value (loading an assembly if it's defined there). Hence a memory is created for readonly variables at run time.

You must note that, here, we are declaring readonly to the variable and not to the memory or the content of the variable. I mean, the meaning of readonly being immutable changes a bit in case of reference type as shown in the below code:

readonly List<string> nameList = new List<string>();

void AddName(string name)
{
  nameList.Add(name);
}

As you can see from the above code, only the variable which is a ref type here is getting readonly restriction rules by compiler but not the content of it.

Hope it helps someone. Smile | :)

Thanks & happy coding.

License

This article, along with any associated source code and files, is licensed under The GNU Lesser General Public License (LGPLv3)

Share

About the Author

zenwalker1985
Software Developer (Senior) Siemens
India India
A .net developer since 4+ years, wild, curious and adventurous nerd.
 
Loves Trekking/Hiking, animals and nature.
 
A FOSS/Linux maniac by default Wink | ;)
 
An MVP aspirant and loves blogging -> https://adventurouszen.wordpress.com/
Follow on   Twitter

Comments and Discussions

 
QuestionGood Stuff PinmentorDave Kerr4-Oct-11 2:49 
AnswerRe: Good Stuff Pinmemberzenwalker19854-Oct-11 5:47 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

| Advertise | Privacy | Mobile
Web03 | 2.8.140922.1 | Last Updated 3 Oct 2011
Article Copyright 2011 by zenwalker1985
Everything else Copyright © CodeProject, 1999-2014
Terms of Service
Layout: fixed | fluid