Difference Between Static, ReadOnly, and Constant in C#

In C#, the keywords static, const, readonly, and static readonly are frequently used, but they can be confusing. Today, we will discuss these keywords and use some examples to better understand them.

Difference-Between-Constant-and-Readonly-Comparison-in-C#
Difference Between Constant ReadOnly and Static-Readonly in C#

Difference between static const and readonly in c#

Following is a comparison of the keywords static, readonly, static-readonly, and constant in C#:

KeywordDescription
staticA static field or property is shared among all instances of a class and is stored in the class itself, rather than in each instance. It is initialized when the class is loaded and remains in memory until the program ends.
readonlyA readonly field or property can only be initialized at the time of declaration or in a Default or parameterized constructor. It cannot be modified after that. It is stored in each instance of the class, so each instance can have a different value for a readonly field.
constA const field or property is similar to a readonly field, but the value is evaluated at compile time and is stored in the assembly metadata. It cannot be modified after that. Constants are usually used for values that are known at compile time and do not change, such as mathematical constants or enum values.
static readonlyIn C#, a static readonly field or property is a field or property that is shared among all instances of a class and is stored in the class itself, rather than in each instance. It is initialized when the class is loaded and remains in memory until the program ends. It is also marked as readonly, which means that it can only be initialized at the time of declaration or in a static constructor, and it cannot be modified after that.
Difference between static const and readonly in c#

Constant Keyword in C#

A constant variable is a type of variable that has a fixed value that cannot be changed at any point in the program. It is stored in the class itself and is by default static, so there is only one copy of it. You can access it directly by using the class name.

  • The const keyword is used to create a constant variable that cannot be changed throughout the program.
  • A constant variable is stored in the class itself, so there is only one copy of it. It can be accessed by all instances of the class and is available globally in the program.
  • We can only initialize a constant variable at the time of declaration, and its value cannot be changed after that.
  • A constant variable can be declared at the class level or inside a method.
  • Every assembly that uses a constant variable receives a copy of it.
  • A constant variable cannot be used with the static keyword. A static variable can be modified, while a constant variable cannot.
  • A constant variable is a compile-time constant, which means that its value is evaluated at compile time and is stored in the assembly metadata.
  • We should not use a constant variable to hold a value that we expect to change at any time. It is intended for fixed values, such as mathematical constants or enum values.
  • The const keyword is useful in a switch statement because C# does not allow a non-constant expression inside the switch.
  • We can use the constant keyword with string variable, null reference, or primitive data types like int, long, double, decimal, byte, short, char, float, bool, etc.
  • The const keyword can be used with the access modifiers like public, private, protected, internal, and protected internal.

Example 1:

In the following code example, we will determine if it is possible to modify the value of a constant variable from within a method or constructor.

const in C#
Const variable in c#

If we attempt to change the value of a constant variable, we will receive a compile-time error.

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

Example 2:

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();
        }
    }
}

In the above program, we can call the const variable PI using the class name without creating an instance of the class.

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

ReadOnly keyword in C#

ReadOnly: In C#, a readonly variable can be initialized at the time of declaration or in the default or parameterized constructor of the same class type. It cannot be re-initialized inside any type of method or static constructor. A readonly variable is a constant that is specific to each instance of a class.

  • The readonly keyword in C# is used to create a readonly variable.
  • A readonly variable can be initialized at the time of declaration or within the constructor(Default or parameterized constructor) of the same class.
  • A readonly variable can only be declared at the class level.
  • A new copy of the readonly variable is created for each instance of the class. It can be accessed using the object of the class and the . operator.
  • A readonly variable can be used with the static keyword as well.
  • A readonly variable is a runtime constant, which means that its value is evaluated at runtime.
  • A readonly field cannot be used as a ref or out value, except in a constructor.
  • The value of a readonly field can be changed, but only in a Default or parameterized constructor.
  • The readonly modifier cannot be applied to local variables.
  • The readonly keyword is useful for preventing the modification of a variable outside the class.
  • We can use the readonly keyword if the value of a variable is unknown at the time of declaration.
  • The readonly keyword can be used with any data type, including value types and reference types.

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

Example 1:

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 ReadOnly program

In the above code example, we re-initialized the readonly variable in the constructor. Now, we will try to re-initialize the variable inside the Main method.

Readonly variable
Trying to reinitialize the read-only variable in the main method

In the above image, we can see that it is not possible to re-initialize the readonly variable inside the Main method. An error message is displayed.

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

Passing readonly variables as ref and out parameters in a constructor.

We already know that readonly variables can be initialized inside the default or parameterized constructor. We can also pass readonly variables as ref or out parameters in a method if the method is called in the constructor context.

Example:

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

If we try to pass a ref or out parameter in a local method, we will receive an error message:

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

Post to read more about the ref and out: 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, such as the StringBuilder class. The readonly modifier prevents a field from being modified by a different instance of a reference type, but it does not prevent the instance data of the field from being modified through the reference type. Therefore, we should not use the readonly modifier for mutable types like collections or arrays, because only the reference cannot be changed, but the object that holds the values can be modified.

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 ReadOnly program

In the above example, we have changed the values of the readonly list. However, if we try to assign the list to a new collection, we will receive a compile-time error because the reference is immutable, but the object itself that holds the value is mutable.

static keyword

In C#, the static keyword can be applied to various elements including classes, variables, methods, properties, constructors, and events. The static modifier creates a single shared copy of an object or data member for all instances to use. It also makes a class or data member non-instantiable, meaning that it cannot be created using the ‘new’ operator. Class members marked as static can be accessed directly using the 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.

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 if the function is static or non-static.
  • We can’t pass static variables as method arguments.
  • A static variable belongs to the class whereas 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.

Example:

Let’s understand how to use the static variable using the following 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 diagram demonstrates how static and non-static data members of a class can be accessed in a program.

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

In the above diagram, it can be seen that static variables can be accessed using the class name, while instance variables can be accessed using an object of the class with the dot operator.

Calling instance variable in the static method

  • In C# Static variables can be accessed by static and non-static methods whereas instance variables can be accessed by only non-static methods.
  • Instance variables are associated with an object. In order to access an instance variable within a static method, it is necessary to create an instance of the class.

Example:

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();
        }
    }
}

Static-readonly keyword in C#

C# 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 a static read-only variable at compile time, but only at 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 program mentioned above, it is possible to change the value of a static read-only variable using a static constructor, but it is not possible to modify the value within a static method.

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

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

Advance – C# Constant keyword: Inspecting library using the ILDASM tool

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

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 variable into the expression

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

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

FAQ

How does Constant differ from ReadOnly in C#?

Both the constant and readonly keywords deal with constant values, however, the value of readonly variables can be set at runtime by the non-static constructors, therefore it can have different values for different objects in the program. The value of constant variables, on the other hand, is common for all the objects and set only during compile time and cannot be changed later.

Can readonly variables be declared at the method level?

No, readonly may only be declared at the class level, not within a method.

Is it possible to declare constant variables at the method level?

Yes, the constant keyword can be declared at the class and method level. constant variables are known as a compile-time constants.

Summary:

In this article, we discussed the differences and similarities between const, static, readonly, static readonly keywords in C# with examples.


I hope this information has been helpful and you have found what you were looking for. Please do not hesitate to share any feedback, questions, or comments you may have.

Recommended Articles

5 1 vote
Article Rating
Subscribe
Notify of
guest

0 Comments
Inline Feedbacks
View all comments