C# Readonly Field Usage

by Sam Allen - Updated January 15, 2010

You want to see an example of how you can use the readonly keyword in the C# programming language and why it may be useful to you. Understand the difference between readonly and constants, and note some compiler errors. Here we see how you can use readonly, and why you may want to. Additionally, we check its performance, using the C# programming language.

=== readonly keyword performance in C# ===                
    Based on .NET 3.5 SP1.                                
    Readonly fields were just as fast as instance fields. 
    Const values were much faster.                        

readonly int:  637 ms 
         int:  635 ms 
   const int:  317 ms  [fastest]

Using readonly field

First, we see an example of how you can use readonly to initialize a DateTime struct. You cannot set a const DateTime, as it raises a compilation error. However, you may need to designate a DateTime field to be unavailable for changes later on. Here, we don't want to mistakenly reset the startup time.

=== Program that uses readonly (C#) ===

using System;

class Program
{
    static void Main()
    {
        Manager manager = new Manager();
        Console.WriteLine(manager.GetStartup());
    }
}

class Manager
{
    readonly DateTime _startup; // <-- the readonly field

    public Manager()
    {
        // Initialize startup time.
        this._startup = DateTime.Now;
    }

    public DateTime GetStartup()
    {
        // We cannot modify the DateTime here.
        return this._startup;
    }
}

=== Output of the program ===

(Current time)

Description. First, the Main entry point is defined, and a new class of type Manager is instantiated. Internally, the Manager class has a constructor. In the constructor, the startup time is initialized. We can actually assign the readonly field here.

Readonly keyword. What the constructor here does is take the current time from the DateTime.Now property and assign it to an unchangeable readonly DateTime field. You are not able to accidentally reassign the startup time.

How readonly benefits us. Your other code, or the code from your team members, can't change the readonly field, making it less likely to be messed up by someone who doesn't understand its purpose.

Inline initialization

Here we see that you can use an inline initialization for readonly. This means that you do not need to put the starting value in a constructor explicitly. In fact, when you open the following code in Reflector, you will see the compiler has put it in the constructor itself.

=== Compiler-generated code (C#) ===

class Manager
{
    readonly DateTime _startup = DateTime.Now; // <-- Same as first example

    public DateTime GetStartup()
    {
        return this._startup;
    }
}

Should I use constants instead?

In many situations, yes. For example, if you have a value that was established outside of your program, such as by science or other research, it is better. Also, if your value is constant and you are in complete control of the program, const is better.

(See Const Example 1.)

DLL issues

When you use a const field or declaration, the C# compiler actually embeds the const variable's value directly in the IL code. Therefore, it essentially erases the const as a separate entity. If programs that depend on a const are not recompiled after the const value changes, they may break.

Benchmark

Here we look at a simple benchmark of readonly and const ints. Also, we include a regular instance of int in the benchmark. In the results, the readonly int and the int field had equivalent performance. The const int was faster by a clear margin. The results were 637 ms, 635 ms, and 317 ms.

=== Class tested (C#) ===

class Test
{
    readonly int _value1;  // 1. readonly int
    int _value2 = 1;       // 2. int
    const int _value3 = 1; // 3. constant int

    public Test()
    {
        _value1 = int.Parse("1");
    }

    public int GetValue1()
    {
        return _value1;
    }

    public int GetValue2()
    {
        return _value2;
    }

    public int GetValue3()
    {
        return _value3;
    }
}

=== Code tested in loops (C#) ===
    Iterations: 1000000000 (many)

Test test = new Test(); // Outside of loops

if (test.GetValue1() != 1) // 1
{
    throw new Exception();
}

if (test.GetValue2() != 1) // 2
{
    throw new Exception();
}

if (test.GetValue3() != 1) // 3
{
    throw new Exception();
}

Error

The author's mistake when using readonly was trying to assign to it in a place that is not a constructor. This will result in the following ugly error when you try to compile:

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

Summary

In this set of examples, we looked at a practical usage of the readonly keyword, and also noted how the first two examples are compiled into IL. Finally, we compared the performance of readonly and const in an object-oriented program. We saw that readonly and regular fields have equivalent performance. You can find a more specific example of readonly fields with the static keyword here.

(See Public Static Readonly Fields.)

(Do not copy this page.)

Dot Net Perls | Search
Language | DllImport and Dllexport for DLL Interop | Global Variable Use | Process.Start Command-Line Examples | Timer Tutorial | WebClient Tutorial
C# | Integer.TryParse | ArrayList Examples | Bituminous Coal | Sleep Method Use
© 2009 Sam Allen. All rights reserved.
Dot Net Perls | Sam Allen