readonly (C# Reference)

The readonly keyword is a modifier that can be used in four contexts:

  • In a field declaration, readonly indicates that assignment to the field can only occur as part of the declaration or in a constructor in the same class. A readonly field can be assigned and reassigned multiple times within the field declaration and constructor.

    A readonly field can't be assigned after the constructor exits. This rule has different implications for value types and reference types:

    • Because value types directly contain their data, a field that is a readonly value type is immutable.
    • Because reference types contain a reference to their data, a field that is a readonly reference type must always refer to the same object. That object isn't immutable. The readonly modifier prevents the field from being replaced by a different instance of the reference type. However, the modifier doesn't prevent the instance data of the field from being modified through the read-only field.

    Warning

    An externally visible type that contains an externally visible read-only field that is a mutable reference type may be a security vulnerability and may trigger warning CA2104 : "Do not declare read only mutable reference types."

  • In a readonly struct type definition, readonly indicates that the structure type is immutable. For more information, see the readonly struct section of the Structure types article.

  • In an instance member declaration within a structure type, readonly indicates that an instance member doesn't modify the state of the structure. For more information, see the readonly instance members section of the Structure types article.

  • In a ref readonly method return, the readonly modifier indicates that method returns a reference and writes aren't allowed to that reference.

The readonly struct and ref readonly contexts were added in C# 7.2. readonly struct members were added in C# 8.0

Readonly field example

In this example, the value of the field year can't be changed in the method ChangeYear, even though it's assigned a value in the class constructor:

class Age
{
    readonly int year;
    Age(int year)
    {
        this.year = year;
    }
    void ChangeYear()
    {
        //year = 1967; // Compile error if uncommented.
    }
}

You can assign a value to a readonly field only in the following contexts:

  • When the variable is initialized in the declaration, for example:

    public readonly int y = 5;
    
  • In an instance constructor of the class that contains the instance field declaration.

  • In the static constructor of the class that contains the static field declaration.

These constructor contexts are also the only contexts in which it's valid to pass a readonly field as an out or ref parameter.

Note

The readonly keyword is different from the const keyword. A const field can only be initialized at the declaration of the field. A readonly field can be assigned multiple times in the field declaration and in any constructor. Therefore, readonly fields can have different values depending on the constructor used. Also, while a const field is a compile-time constant, the readonly field can be used for run-time constants as in the following example:

public static readonly uint timeStamp = (uint)DateTime.Now.Ticks;
public class SamplePoint
{
    public int x;
    // Initialize a readonly field
    public readonly int y = 25;
    public readonly int z;

    public SamplePoint()
    {
        // Initialize a readonly instance field
        z = 24;
    }

    public SamplePoint(int p1, int p2, int p3)
    {
        x = p1;
        y = p2;
        z = p3;
    }

    public static void Main()
    {
        SamplePoint p1 = new SamplePoint(11, 21, 32);   // OK
        Console.WriteLine($"p1: x={p1.x}, y={p1.y}, z={p1.z}");
        SamplePoint p2 = new SamplePoint();
        p2.x = 55;   // OK
        Console.WriteLine($"p2: x={p2.x}, y={p2.y}, z={p2.z}");
    }
    /*
     Output:
        p1: x=11, y=21, z=32
        p2: x=55, y=25, z=24
    */
}

In the preceding example, if you use a statement like the following example:

p2.y = 66;        // Error

you'll get the compiler error message:

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

Ref readonly return example

The readonly modifier on a ref return indicates that the returned reference can't be modified. The following example returns a reference to the origin. It uses the readonly modifier to indicate that callers can't modify the origin:

private static readonly SamplePoint origin = new SamplePoint(0, 0, 0);
public static ref readonly SamplePoint Origin => ref origin;

The type returned doesn't need to be a readonly struct. Any type that can be returned by ref can be returned by ref readonly.

C# language specification

For more information, see the C# Language Specification. The language specification is the definitive source for C# syntax and usage.

You can also see the language specification proposals:

See also