Constant vs ReadOnly vs Static in C#

This is one of the frequently asked C# interview question for the beginners. Constant, ReadOnly and Static are keywords that are nearly the same in behavior but confusing. In this article I will explain differences among const, readonly and static keywords. You will be able to understand their different behavior and operation.


Constant

Constant field or variable must be initialized at the time of declaration. If you are assigning an expression in a constant field or variable then its value must be evaluated at compile time otherwise compiler will give an error during compilation. That’s why it is also called compile-time constant.

public class Demo
{
   public const int val1 = 25;
   
   public void Operation(int arg1, int arg2)
   {
     const int val2 = 30;
     const int val3 = val1 + val2;	//55
     const int val4 = val1 + arg2;	//compile time error as expression is not evaluated
   }
}

const keyword can be used with built-in value types (byte, short, int, long, char, float, double, decimal, bool), enum, a string literal, or a reference type which can be assigned with a value null.

const Demo obj1 = null; 		//No error, since its evaluated a compile time
const Demo obj2 = new Demo(); 	//Throws an error, since its evaluated at run time

We cannot define a constant as static.

How it works internally in MSIL?

Whenever you declare a constant variable, the C# compiler substitutes its value directly into the Intermediate Language (MSIL). Let’s understand with an example:

public class AppConstants
{
    public const string Message = "Hello!"; 
}
public class Test
{
    string name = "Manish";
    public string GetMessage()
    {
       string result = name + AppConstants.Message;
       return result;
    }
}

Let’s check in MSIL, how it looks:



Hello is directly replaced in placed of AppConstants.Message. It means any modifications you do to the const variable would result in something similar to below.

public class AppConstants
{
    public const string Message = "Hello!"; 
}
public class Test
{
    string name = "Manish";
    public string GetMessage()
    {
	/* This statement will throw an error as it internelly becomes "Hello!" = "Hi!", which is mot vallid
        */
       AppConstants.Message = "Hi!"; 
       string result = name + AppConstants.Message;
       return result;
    }
}

After going through this example and understanding concept, we can say that constants are immutable and cannot be changed during life of programe otherwise it will throw and error.


ReadOnly

ReadOnly field can be initialized at the time of declaration or with in the constructor of same class. We can also change the value of a ReadOnly field at runtime or assign a value to it at runtime but in a non-static constructor only. That’s why it is also called run-time constant.

public class Demo
{
   public readonly int val1 = 25;
   
   public Demo()
   {
     val1 = 20;
   }
   public void Operation(int arg1, int arg2)
   {
     val1 = 10; 	//Throws error as we can not changed value or readonly aprt from constructor
     int val2 = 30;
     int val3 = val1 + val2;
   }
}

The readonly variable is assigned a value at the time of the declaration and is accessed using the instance of the class rather than using the class itself. You may have multiple instances of the class, which might have the readonly variable assigned to a different value.

public class Demo
{
   public readonly int val1 = 25;
   
   public Demo()
   {
     val1 = 20;
   }
   public void Operation(int arg1, int arg2)
   {
     int val2 = 30;
     int val3 = val1 + val2;
   }
}
             
public class Program
{
   static void Main(string[] args)
   {
      Demo obj1 = new Demo(10);
      obj1.Operation();
      Demo obj2 = new Demo(40);
      obj2.Operation();	
   }
}

Readonly keyword can be used with built-in value types (byte, short, int, long, char, float, double, decimal, bool), enum, a string literal, or a reference type.

How it works internally in MSIL?

In case of read-only variable, C# compiler does not substitute its value directly into the Intermediate Language (MSIL). Its value is decided on runtime. Let’s see in below example:

public class AppConstants
{
    public readonly string Message = "Hello!"; 
}
public class Test
{
    string name = "Manish";
    public string GetMessage()
    {
       string result = name + new AppConstants().Message;
       return result;
    }
}

Let’s check in MSIL, how it looks:



Here you can see in image, value is not replaced. Value is accessed by object of class.

After going through this example and understanding concept, we can say that readonly variables are also immutable values which are known at run time and do not change their values for the life of the program.


Static

Static keyword is used to specify a static member. Static members are common to all objects which mean data is shared among all objects. If we declare a class as a static class then all the class members must be static too. This keyword can be used with classes, fields, methods, properties, operators, events, and constructors, but it cannot be used with indexers, destructors, or types other than classes.

Static field can be initialized at the time of declaration or anywhere within a class or outside of a class. Static methods can only access static members of same class. Static properties are used to get or set the value of static fields of a class.

public class Demo
{
   public static int val1 = 25;
   
   public void Operation(int arg1, int arg2)
   {
     val1 = 10;
     int val2 = 30;
     int val3 = val1 + val2;
   }
}

Difference

Constant ReadOnly Static
InitializationConstants can be initialized only at the time of declarationReadOnly field can be initialized at the time of declaration or with in the constructor of same classStatic variables can be initialized at the time of declaration or with in the class.
How to Access?Constant variables have to be accessed using "Classname.VariableName"Read only variables have to be accessed using the "InstanceName.VariableName"Static variables have to be accessed using the "InstanceName.VariableName"
Compile Time vs Run TimeConstants are known at compile timeRead only variables are known at run time.Static variables are known at both either at compile time or run time
When can change value?Cannot be changed during life of programeCannot be changed during the life or programe apart from non-static constructorCan be changed during life of programe
When to use?Use when you sure that the value a field or local variable would not be changed.Use when you want to make a field constant at run time.Use when you want to share common data among all instances.
Can be static?NoYesYes