Difference Between Const, static, ReadOnly and Static ReadOnly variables in C#

Introduction

In this article, we will discuss the const, readonly, static, and static readonly keywords in detail.

C# static keyword

In C#,  static  is a keyword that can be applied to classes, variables, methods, properties, constructor and events.

The static modifier is useful to create a single copy of an object (class or data members) to share common data among all the instances.
The static modifier makes a class or data member non-instantiable, that means if we mark a class as static it will not allow us to create an object using the  new  operator.
A class member declared as static can be accessed directly by its class name.

The static keyword in C# is used to define static members which are common to all the objects and not bound to any specific object.

Static variable memory allocation

Static variable in C#
Static variable memory allocation in high-frequency heap

In C#, static and constant data exist for the lifetime of the application, therefore they stored in a high frequency heap and can’t be garbage collected.
A high frequency heap is a kind of loader heap that exists for each AppDomain where all the static data are stored.

C# Static Variables

We can declare a variable as  static  if we want to share the same value throughout all the instances of that class.

Following are some important points about the static variables in C#.

    • A static variable is a class-level variable that can call directly by the class name without creating an instance of that class.
    • A static variable creates only a single copy in the high-frequency heap memory and all the objects of the class share the same copy.
    • Any changes in the value of the static variable will get reflected in all instances where it is used.
    • In C#, we can’t declare static variables at the function level, It doesn’t matter the function is static or non-static.
    • We can’t pass static variables as method arguments.
    • A static variable belongs to the class were as an instance variable belongs to an object.
    • A static variable can call directly by the class name (Example: MyClass.myVariable).
    • An instance variable can access by the object of the class using the dot .   operator.
    • A static property can get or set the value of a static field of a class only.

Let’s understand the static variable using the below example:

using System;
namespace StaticDemo
{
    public class User
    {  
       // static variable
        public static int userId = 100;

        // instance variable
        public string userName = "Shekh Ali";
    }

    class Program
    {
        static void Main(string[] args)
        {

            //Static members can access directly by the class name.
            Console.WriteLine($"Id= {User.userId}");

            //error, because we can access only static variable by using class name.
            //Console.WriteLine($"{User.name}"); 

            //To access instance variable we have to create object of the class.
            User objUser = new User();

            Console.WriteLine($"Name = {objUser.userName}");

            Console.ReadLine();
        }
    }
}


Static variable result:
The output of the above program.

The following is the pictorial diagram to illustrate how static and nonstatic data members of a class can be accessed in the program.

static variable vs instance variable in C#
Calling static and instance variables.

We can see in the above diagram that the static variable can be accessed by using the class name where instance variable can access by using the object of the class using the “.” operator.

Calling instance variable in the static method

In C# Static variables can be accessed by static and non-static methods where instance variables can be accessed by the only non-static methods.

Instance variables belong to the object. To access an instance variable inside the static method we must create an instance of the class.

Example code:

using System;
namespace StaticDemo
{
    public class User
    {
     // static variable
        public static int userId = 100;

        // instance variable
        public string userName = "Shekh Ali";

        //static method
        public static void StaticMethod()
        {
            Console.WriteLine(" Static method ");

            //static members can call by class name
            Console.WriteLine(User.userId);

            //Instance variable will call using the object
            //inside the static method
            User obj = new User();
            Console.WriteLine(obj.userName);
        }

        // Instance method
        public void InstanceMethod()
        {
            Console.WriteLine(" Instance method ");
            //Calling instance variable
            Console.WriteLine($"Name: {userName}");
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            User.StaticMethod();
            User user = new User();
            user.InstanceMethod();
            Console.ReadLine();
        }
    }
}



Constant keyword in C#

Constant: The const keyword is used to define the variables that need to have values at compile-time and by default they are static.
As const variables are static by default, that’s why they can be referenced through “ClassName.VariableName“.

In C#, the  constants  are immutable.

A variable whose value once assigned can’t modify further by any means during the execution of the program is called  constant  variable. constant variable creates a single copy and shared among all the objects. It can access directly by the class name.

Following are few important points about the const variables.

      • The const keyword is used to create a constant variable.
      • We can only initialize a constant variable at the time of declaration.
      • We can declare the constant variable at the class level or inside a method.
      • const variable creates a single copy and can access globally in the program.
      • const variables are static by default that’s why they can access directly by the class name.
      • We can’t use a const variable with the static keyword.
      • A static variable can modify where a constant variable can never modify.
      • A const field is a compile-time constant.
      • Don’t create a constant to hold the value that we expect to change at any time.
      • The const is useful to hold fixed value only. (Example PI = 3.14)
      • The const is useful in a switch statement as C# doesn’t allow a non-const statement inside the switch

constant variable creates a single copy and shared among all the objects. It can access directly by the class name.

We can use the  const  keyword with string variable, null reference, or primitive data types like int, long, double, decimal, byte, short, char, float, bool, etc.

We can use the const keyword with the access modifiers like public, private, protected, internal, and protected internal.

Let’s try to change the value of a constant variable inside the constructor or method.

const in C#
In the above image, we can see that the value of the constant variable can’t be changed once assigned

If we try to change the value in the constant variable, it will throw compile-time error.

The left-hand side of an assignment must be a variable, property or indexer

Following are the example of constant variable in C#:

using System;
namespace ConstantDemo
{
   class Constant
    {

     // Initializing const variable.

      public  const double PI = Math.PI;      

    }
    class Program
    {      
        static void Main(string[] args)
        {

            Console.WriteLine($"PI = {Constant.PI}");

            Console.ReadLine();
        }
    }
}

Output of the above Constant program:
Output after executing the above program.

In the above program const variable ‘PI’ is calling by the class name without creating an object of the class.

Inspecting library using the ILDASM tool in.net

The value of the constant fields gets stored inside the .dll or .exe during the compilation time. Which can be seen using the ILDASM tool.

The constant variable in c#

In the above example, we can see that the value of the constant variable ‘PI’ is directly embedded into the IL Code. As we know that constant fields are by default static which can be seen in IL code as well.

In C#, The constructors don’t have return types not even void. But after compilation to IL, a constructor has a return type of void. We can see in the above image (.ctor: void())

Use of constant field into the expression

Constant allows us to use only the constant fields into the expression. We can’t assign an integer or any other data type variable to a constant variable.

Example:

using System;
class Program
{
    const int x = 5;

    const int y = 10; 

    const int z = x + y; //Correct, It will work fine.

    int a = 20;
    //const int b = a ; // Compile time error because 'a' is an integer type.

    static void Main(string[] args)
    {
        Console.WriteLine($"z = {z}");

        Console.ReadLine();

    }
}

//Output: z = 15

ReadOnly keyword in C#

In C# a  readonly  variable can be initialized at the time of declaration or by Default or parameterized constructor of the same class type. It can’t be reinitialized again inside any type of method or static constructor. The readonly variable is an object-level constant.

      • In C#, readonly keyword is used to create a readonly variable.
      • We can initialize a readonly variable at the declaration time or within the constructor of the same class.
      • We can declare the read-only variable at the class level only.
      • A new copy of the readonly variable is created for each instance of the class.
      • A readonly variable belongs to the object and can access by using the object of the class using the “.” operator.
      • We can use a readonly variable with the static keyword as well.
      • The read-only variable is runtime constant variable.
      • The value of the readonly field can be changed.
      • In C# the readonly modifier can’t apply to the local variables.
      • The readonly is useful for preventing modification of a variable outside the class.
      • The readonly can be used if the value is unknown at the declaration time.
      • In C# we can use the read-only keyword with any data type ( value type/reference type ).

Note: The readonly variables are useful if we want to have different constant values for the different instances of the class.

Example of the readonly variable

using System;
namespace ReadOnlyDemo
{
    class User
    {
        public readonly double id = 123;

        public readonly DateTime currentDate;

        public User()
        {
            currentDate = DateTime.Now;
            // Value can be changed inside the default/parameterized constructor
            id = 456;
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
          // readonly int localVariable = 10; // error : The modifier readonly is not 
                                              //         valid for this item

            User user = new User();

            Console.WriteLine($"Id = {user.id} CurrentDate :{user.currentDate}");

            Console.ReadLine();
        }
    }
}


output of readonly program in c#
The output of the above program

In the above program, we have reinitialized the read-only variable in the constructor. Now let’s try to reinitialize the variable inside the Main method.

Trying to reinitialize the read-only variable in the method

In the above image, we can see it doesn’t allow us to reinitialized the read-only variable inside the main method. It displays the error message.

A read-only field cannot be assigned to (except in a constructor or a variable initializer)

Passing readonly variables as ref/out parameters in the Constructor

As we know that the readonly variables can be initialized inside the default or parameterized constructor.
We can pass readonly variables as ref or out in method parameter if the method is called in the constructor context.

Let’s create a simple program.

using System;
namespace ReadOnlyDemo
{
    class User
    {
        public readonly int a = 5;

        public readonly int b = 10;   
   
        public User()
        {
            //We can pass ref or out parameter in constructor context only.
            Print(ref a, out b);
        }

        public void Print(ref int a, out int b)
        {
            a = 10;
            b = 20;
            Console.WriteLine($"a: {a} , b: {b}");
        }


    }
    class Program
    {
        public readonly int x = 30;
        public readonly int y = 40;

        static void Main(string[] args)
        {
          
             User user = new User();

             Program p = new Program();
           // user.Print(ref p.x, out p.y);// error:
          // A readonly field cannot be used as ref or out vale (except in a constructor)

            Console.ReadLine();
        }
    }   
}
 //Output: a: 10 , b: 20

We can’t  pass ref or out parameter in the local method otherwise it will throw the following error message:

A readonly field cannot be used as ref or out vale (except in a constructor)

Read the following article to know more about the ref and out keywords.

Difference between Ref and Out keywords in C#

Do not declare readonly to mutable reference types

A mutable type is a type whose instance data can be modified (example: StringBuilder).
As we know that the read-only modifier prevents the field from being modified by a different instance of the reference type.
The read-only does not prevent the instance data of the field from being modified through the reference type.
So, we should not assign read-only to mutable types like collection or arrays because only the reference cannot be changed but the object that holds the values can be changed.
Example code:

using System;
using System.Collections.Generic;

namespace ReadOnlyDemo
{
    class MyClass
    {
        public readonly List<int> myList;
 
        public MyClass()
        {
            //initializing myList in the constructor

            myList = new List<int>() { 10, 20, 30 };

        }

    }
    class Program
    {
       

        static void Main(string[] args)
        {

            MyClass obj = new MyClass();

            // Violation of readonly rule
            obj.myList[0] = 5; // value 10 is replaced by 5

            foreach(int item in obj.myList)
            {
                Console.Write(item + "  ");
            }

           // obj.myList = new List<int>(); //Invalid

            Console.ReadLine();
        }
    }

    //Output: 5, 20, 30,
}



The output of the above read-only program:
The output of the above program

In the above example, We can change the values of the read-only list.
When we try to assign the list to the new collection, It will throw a compile-time error because only the reference is immutable not the object itself that holds the value.

Static Read-Only keyword

static readonly keyword: The static readonly variable is very similar to the const variable. We can initialize the static readonly variable at the compile-time or by using the static constructor only.

The compiler does not have access to the value of the static read-only at the compile time but only at the runtime.

Following is the program for the example.

using System;
namespace StaticReadOnly
{
    public class User
    {   
        // static readonly variable
        public static readonly int id = 100;

        //static constructor
        static User()
        { 
            Console.WriteLine(" Static Constructor ");
            id = 30; //reinitialize the variable
            Console.WriteLine($"Id: {id}");
        }
        //static method
        public static void StaticMethod()
        {
            Console.WriteLine(" Static method ");
            // id = 20; // It will throw error
            Console.WriteLine($"Id: {id}");
        }

    }
    class Program
    {
        static void Main(string[] args)
        {
            User.StaticMethod();
            Console.ReadLine();
        }
    }
    /* Output: 
      Static Constructor
       Id: 30
      Static method
       Id: 30
     */
}



In the above program, It allows us to change the value in the static constructor, but we can’t change the value of the static read-only variable in the static method.

If we try to change the value in the static method, it will throw compile-time error.

A static readonly field cannot be assigned to (except in a static constructor or a variable initializer)

Summary:

In this article, we discussed about the differences and similarities between const, static, readonly, static readonly keywords in C# with examples.
I hope you enjoyed this post and found what you were looking for. In case you have any doubt, please post your feedback, question, or comments.

Thanks for visiting.

Leave a Reply