Monday, July 21, 2014

C# Constants vs. Readonly fields. (what will happen in compile time and run time)

Hi guys, after long time, back to blogging.

I wanted to discuss some fundamental stuffs on C#.
Let’s begin with some key facts related to constants and readonly fields.

1. Constants:


In C# constant can define using const key word as follow.


public const int CMStoM = 100;

Important:

  • Value of a constant evaluated at compile time. Because of that, it must be initialized at the declaration.
  • As name implies we can’t change a value of a constant after we created it.
  • We can neither use ‘virtual’ nor ‘static’ modifiers with constants.
  • Allowed types for a constant are sbyte, byte, short, ushort, int, uint, long, ulong, char, float, double, decimal, bool, string, an enum-type or a reference-type.
  • However, other than a string value or null value we can’t assign any other reference type for a constant. 
  • So if you try to initialize a constant using any other reference type you will ended up with following compile error: “A const field of a reference type other than string can only be initialized with null.

Think about following scenario...

When your constant field is being referred from another assembly..
As an example let’s take following code blocks,
// assembly_1
public class Constants
{
  public const string CONST_STRING = "This is a Constant.";
}

// assembly_2
public class ClassB
{
  public void DisplayString()
  {
    Console.WriteLine(Constants.CONST_STRING);
  }
}

Suppose these classes are belongs to two different assemblies (i.e. assembly_1 and assembly_2 as shown in the comments).
So when compiling ClassB, value of the constant will directly copied to the assembly_2. (Please refer following image which shows the IL code of ClassB)


As you can see value has been copied at compile time and it is not required to lookup in run time. So there is an advantage in performance wise.

But if we change the CONST_STRING in Constants class then, ClassB will not get the modified value until we recompile assembly_2.

So we should keep in mind these thing when we are using constants.

2. Read Only Fields:


In C# read only field can define using readonly key word as follow.
public readonly int width = 10;

Important:

  • We can assign a value to read only field, only in following two contexts.
    • Where it has been declared.
    • In a constructor of the class which contains the field. When the field is static we can do the assignment only in the static constructor and if it is an instance field, then assignment can be done only in a instance constructor.
    • (Theoretically we cannot change the value of a read only field outside above boundaries. We can however, violate that using .NET Reflection. Let’s discuss that in a separate post.)
  • Most important thing is that within above context, we can do the assignment more than once. Therefore in that context we can pass them as an out or ref parameter.
  • It is possible to create a read only field type of a, reference type and initialize. (Compare this with the constants)
Example:
public readonly List<string> listOfStrings = new List<string>();

  • Read only fields are evaluated at run time. So they can be used as run time constants.
Example:
public static readonly uint randomConstant = (uint)DateTime.Now.Ticks;

Think about following scenario...

When your read only field is being referred from another assembly..
Let’s consider code blocks which we used in constants section with some modifications.

 // assembly_1
  public class Constants
  {
    public static readonly string ReadOnlyString = "This is read only.";
  }

  // assembly_2
  public class ClassB
  {
    public void DisplayString()
    {
      Console.WriteLine(Constants.Constants.ReadOnlyString);
    }
  }

Since value of a readonly field is evaluated at run time, reference to the field will be created in compiled ClassB (in IL code). Following image shows IL code of ClassB.


Therefore if we change the value of ReadOnlyString, it is not required to compile assembly_2. But there can be a trivial performance issue when it’s compared with a Constant(Compare this fact with a constant field as described above.)

So we have to consider these facts, to properly use constant and readonly fields.

Happy coding..!!