Thursday, September 12, 2019

C# Const, ReadOnly & Static ReadOnly Differences

C# Const makes fields or locals constant.ReadOnly applies to fields in C#, value is constant after initialization.Static ReadOnly makes ReadOnly field class member.(Can be accessed through class name)
Please go through the summary of differences between const and readonly then I will try to explain each point after that.

Table Of Contents:

  • Const vs Readonly in C#
  • C# Const field or local
  • C# ReadOnly Field
  • Versioning problem of the Const field in C#
  • C# Static Readonly field
  • C# Readonly vs Static Readonly
  • When to use Const and When to use readonly in C#

Const vs Readonly in C#:

ConstReadonly
const keyword can be applied to fields or local variablesreadonly keyword applies only to fields not local variables
We must assign const field at the time of declation onlyWe can assign readonly field at the time of declaration or in constructor,not in any other methods.
No Memory Allocated Because const value embedded in IL code itself after compilationdynamic memory allocated for readonly fields and we can get the value at run time.
Const in C# are by default static.Can be accessed only through class nameReadonly belongs to the object created so accessed through only through instance of class. To make it class member we need to add static keyword before readonly.
We can declare following built in (primitive types) datatypes as const Boolean,Char, Byte, SByte, Int16, UInt16, Int32, UInt32, Int64, UInt64, Single, Double, Decimal and also string.Same as Const
The value is constant (as it is belongs to class)The value may be different depending upon constructor used (as it belongs to object of the class)
If we want to declare const for someclass (non-primitive types) we should assign it to null which as of no use.If you declare a non-primitive types (reference type) as readonly only reference is immutable not the object it contains.(see the example below)
Do not use const field that might change over the time it leads to dll version problem
(see the example)
As the value obtained at run time there is no dll versioning problem with static readonly fields
Const field can not be passed as ref or out parameterWe can pass readonly field as ref or out parameters in the constructor context.

ReadOnly and Constant in C#
ReadOnly and Const in C#

C# Const field or local:

We will use keyword “const” to declare Constant fields or locals in C#.
Whenever you are defining a const field its value must be assigned at the time of declaration itself, after that we cannot change its value. Go through the following example to understand it
        
        Public class Program
        {
           const int fieldConstant = 10; //Field

           static void Main(string[] args)
           {
             const int X = 10, Y = 50; //Correct //Local Variable
             const int Z = X + Y;      //Correct
             const int A = X + GettheValue(); // Error
           } 
           public static int GettheValue()
           {
             const int localx=10;
             return 10;
           }
        }

The first two lines will works without any errors because X,Y,Z field values are evaluated at the time of compile time itself. But in 3rd line we declared a variable ‘A’ as const and trying to evaluate its value at runtime using GettheValue() method.The line will not execute because const variables must be assigned at the time of compile time itself.
Field in C# is a variable that is declared directly in a class or struct
In the above example fieldConstant is a field because its directly declared inside program class.
And we can declare local variables as const as shown in above GetTheValue() method.
The following built in value types can be declared as Const: int, long, char, float, double, decimal, bool, byte, short, string variable as const.
And we can assign non-primitive types to null to define a const.But it’s useless to declare a const reference type which is assigned to null.
            const string constantString = "Hi Iam Constant"; //Correct
            const Program program = new Program(); //Error
            const Program program1 = null; //Correct

You cannot declare a const variable as static because const fields are considered as static members by default.
            ReadonlyConstant r1=new ReadonlyConstant();// Please see the below code for class declaration

            Console.WriteLine(r1.ynumber);              //Error
            Console.WriteLine(ReadonlyConstant.ynumber);//Correct

As the const variable by default static, you cannot access it from the instance of the class. And we cannot pass const values as ref or out params.

C# ReadOnly Field:

We can declare fields as Readonly in C# not local variables.
ReadOnly fields can be initialized at the time of declaration or only within the constructor which is called only once at the time of object creation, not in any other method.
    public class ReadonlyConstant
    {
        
        public const int numberOfDays = 7; //Field
        public readonly double PI=3.14;             //inline intialization
        
        public readonly int znumber;
        public readonly List<int> readonlyList;

        public ReadonlyConstant()
        {
            znumber= 50;//Constructor initialization            
        }

        public ReadonlyConstant(int x)
        {
             znumber=100;
        }
        
        public NormalMethod()
        {
            //readonly int i=0; This is wrong
        }
    }

And the value may be different depending upon the constructor used. i.e., readonly field belongs to object of the class.
Please read the further article about readonly field to understand it further.
Now we will go through the differences between const and readonly fields, As mentioned in the second point for const fields no memory allocated and the value directly embedded in IL code. please see the below picture of IL code. (Few differences explained in above post)
Constant-Readonly-IL-Code
Const Readonly-IL-Code
I used resharper tool to see Intermediate Language(IL) code of above sample program (ReadonlyConstant.cs)
As you can see the IL code of const field numberOfdays value (7) directly embedded into IL code. Where as the readonly field piValue is displayed as piValue i.e., the value can be obtained at run time.
This leads to versioning problem.

Versioning problem of the Const field in C#:

I compiled above sample program as a class library(A) and used it in another project (in B) as a reference.  Now see the generated IL code of project B
Readonly and Constant field difference at IL Code
Readonly-Const-IL-Code
And Even in project B IL code, the value of const field numberofdays embedded in IL code. Now the problem is, in the source (in A ReadonlyConstant.cs library) the const field (numberOfdays )value changed to 5 and compiled and generated a new dll.
But this new value of the const field does not affect in project B until unless we compile the project. After compilation the new const field value will be embedded in IL code of project B.
To overcome this problem we will use static readonly fields.

C# Static Readonly field:

As the readonly field value is different depending upon the constructor used (As explained in the above article). To make it class member (static member) and unique to the class, we will add static keyword before the variable as shown below.
public class ReadonlyStatic
{
   public static readonly string x = "Hi";
   public static readonly string y;

   public ReadonlyStatic()
   {
     //y = "Hello"; This is wrong
   }

   static ReadonlyStatic()
   {
      y = "Hello";
   }
}
Now we can use it as constant across the class will overcome the dll version problem with const variables.There may be some performance issues but no need to build the destination project as the value can be obtained at run time.
As shown in the above example we can assign static readonly fields at the time of declaration or in static constructor only.
remaining differences I explained in above readonly article (as the post is becoming large I thought of splitting it two)

C# Readonly vs Static Readonly:

Following are the main differences between readonly and static readonly fields in C#.
Readonly in C#Static Readonly in C#
Can be assigned at the time of declaration or constructorCan be assigned at the time of declaration or static constructor
Value may be different depending upon the constructor usedValue will be constant after the initialization

When to use Const and When to use readonly in C#

Use const when the value is absolute constant that won’t change over the time. For example Number of days in a week is 7. This is always constant. and when in doubt use static readonly to avoid the dll versioning problem.
As the const field value embedded inside IL. Use const modifier for absolute constants to gain performance benefits.
And as explained in the above readonly article if we want to use different constant values for a different instance of the class (or objects) use readonly.

No comments:

Post a Comment

Get max value for identity column without a table scan

  You can use   IDENT_CURRENT   to look up the last identity value to be inserted, e.g. IDENT_CURRENT( 'MyTable' ) However, be caut...