C# Const vs Readonly


Const

The const keyword declares constants – values that won’t change throughout the lifetime of a program. Constants are initialized on declaration and are static by default. At compile time, the compiler replaces all usages with the constant’s literal value.

const int INCHES_IN_A_FOOT = 12;

const int CM_IN_A_METRE;
//Fails because it's
// not initialized on declaration

The constant-to-literal substitution has a downside – all external consumers of a constant have to be rebuilt if it changes. For example, should pi be a const or readonly? Using const should be fine however if precision requirements change often, then using readonly removes the need for excessive downstream re-compilation.

It is semantically correct to use the const qualifier for reference types but this serves no purpose. Constants have to be initialized at declaration and only null values are allowed for reference types (strings are the only exception). Moreover after such null initializations, the constants cannot be changed anymore. What’s the use of a null const?

const List intList = new List{1,2,3};
//fails, only null values are
//allowed for const reference types

const List intList2 = null;
//compiles but useless
// as it cannot be changed anymore

Readonly

Unlike constants which MUST have values declared at initialization, readonly values can be set at declaration or in the constructor. Once set, readonly values cannot be changed anymore; such attempts will result in exceptions. Since constructors can be overloaded, a readonly value is determined by its construction path.

using System;

public class Test
{
    public readonly int rdOnly = 3;
    
    public Test(int rdVal)
    {
        rdOnly = rdVal;
        Console.WriteLine(rdOnly);
    }

    public Test()
    {
        rdOnly = 5;
        Console.WriteLine(rdOnly);
    }

    public Test(string s)
    {
        Console.WriteLine(s);
        Console.WriteLine(rdOnly);
    }

    public static void Main()
    {
        Test test1 = new Test(100);
        //100

        Test test2 = new Test();
        //5

        Test test3 = new Test("Hello");
        //3

        test3.rdOnly = 2000;
        // compile error
     }
}

If there is any chance that a ‘constant’ value might change and a lot of assemblies use it; it’s better to use readonly – this removes the need for re-compiling a lot of modules downstream.

Differences between const and readonly

  1. Const values are always implicitly static while readonly values are not.
  2. Const values have to be initialized on declaration while readonly values can be set on declaration or in the constructor – the only rule is that the value must be set before the constructor exits.
  3. On compilation, all const values are replaced with their literal values globally while readonly usages contain a reference to the sole declaration.

Caution! Usage Gotcha

Marking a reference type as readonly ‘freezes’ the reference and not the referenced value. The readonly reference cannot be replaced by another however you are free to change the contents of the reference object!

public class ReadonlyCheck
{
    readonly Point rdOnlyP
      = new Point(0,0);

    public ReadonlyCheck()
    {
        rdOnlyP.xcoord = 5;
        //succeeds
        rdOnlyP = new Point(1,1);
        //fails
    }
}

Conclusion

This post explained the difference between the readonly and const keywords in C# and explained when and how to use them. Here are a couple more posts you might enjoy:

1. Understanding Tail Recursion

2. Programming Language Type Systems I

3. Programming Language Type Systems II

One thought on “C# Const vs Readonly

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.