readonly (Referencia de C#)

La palabra clave readonly es un modificador que se puede usar en cinco contextos:

  • En una declaración de campo, readonly indica que la asignación a un campo solo se puede producir como parte de la declaración o en un constructor de la misma clase. Se puede asignar y reasignar varias veces un campo de solo lectura dentro de la declaración de campo y el constructor.

    No se puede asignar un campo readonly después de que el constructor salga. Esta regla tiene diferentes implicaciones para los tipos de valor y tipos de referencia:

    • Debido a que los tipos de valor contienen directamente sus datos, un campo que es un tipo de valor readonly es inmutable.
    • Dado que los tipos de referencia contienen una referencia a sus datos, un campo que es un tipo de referencia readonly debe referirse siempre al mismo objeto. Es posible que ese objeto no sea inmutable. El modificador readonly impide reemplazar el valor de campo por una instancia diferente del tipo de referencia. Sin embargo, el modificador no impide que los datos de instancia del campo se modifiquen a través del campo de solo lectura.

    Advertencia

    Un tipo visible externamente que contenga un campo de solo lectura visible externamente que sea un tipo de referencia mutable puede ser una vulnerabilidad de seguridad y puede desencadenar la advertencia CA2104: "No declarar tipos de referencias mutables de solo lectura".

  • En una definición de tipo de readonly struct, readonly indica que el tipo de estructura es inmutable. Para obtener más información, vea la sección struct readonly del artículo tipos de estructura.

  • En una declaración de miembro de instancia dentro de un tipo de estructura, readonly indica que un miembro de instancia no modifica el estado de la estructura. Para obtener más información, vea la sección Miembros de instancia readonly del artículo Tipos de estructura.

  • En una devolución del método ref readonly, el modificador readonly indica que el método devuelve una referencia y las operaciones de escritura no se permiten en esa referencia.

Ejemplo de campo readonly

En este ejemplo, el valor del campo year no se puede cambiar en el método ChangeYear, aunque se asigne un valor en el constructor de clase:

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

Solo se puede asignar un valor a un campo readonly en los siguientes contextos:

  • Cuando la variable se inicializa en la declaración, por ejemplo:

    public readonly int y = 5;
    
  • En un constructor de instancia de la clase que contiene la declaración de campo de instancia.

  • En el constructor estático de la clase que contiene la declaración de campo estático.

Estos contextos de constructor son también los únicos en los que es válido pasar un campo readonly como parámetro out o ref.

Nota

La palabra clave readonly es diferente de la palabra clave const. Un campo const solo se puede inicializar en la declaración del campo. Un campo readonly se puede asignar varias veces en la declaración de campo y en cualquier constructor. Por lo tanto, los campos readonly pueden tener diferentes valores en función del constructor que se use. Además, mientras que un campo const es una constante en tiempo de compilación, el campo readonly puede usarse para constantes en tiempo de ejecución, como muestra el siguiente ejemplo:

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
    */
}

En el ejemplo anterior, si se usa una instrucción como el ejemplo siguiente:

p2.y = 66;        // Error

se obtiene el siguiente mensaje de error del compilador:

No se puede asignar un campo de solo lectura (excepto en un constructor o inicializador de variable) .

Miembros de instancia de solo lectura

También puede usar el modificador readonly para declarar que un miembro de instancia no modifica el estado de una estructura.

public readonly double Sum()
{
    return X + Y;
}

Nota:

En el caso de una propiedad de lectura y escritura, puede agregar el modificador readonly al descriptor de acceso get. Algunos descriptores de acceso get pueden realizar un cálculo y almacenar en caché el resultado, en lugar de simplemente devolver el valor de un campo privado. Agregar el modificador readonly al descriptor de acceso get garantiza que el descriptor de acceso get no modifique el estado interno del objeto almacenando en caché ningún resultado.

Puede encontrar más ejemplos en la sección miembros de instancia readonlydel artículo Tipos de estructura.

Ejemplo de devolución de Ref readonly

El modificador readonly en un elemento ref return indica que la referencia devuelta no se puede modificar. En el ejemplo siguiente se devuelve una referencia al origen. Usa el modificador readonly para indicar que los autores de la llamada no pueden modificar el origen:

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

No es necesario que el tipo devuelto sea una readonly struct. Cualquier tipo que pueda devolver ref también puede devolver ref readonly.

Ejemplo de readonly ref readonly return

También se puede usar ref readonly return con miembros de instancia readonly en tipos struct:

public struct ReadonlyRefReadonlyExample
{
    private int _data;

    public readonly ref readonly int ReadonlyRefReadonly(ref int reference)
    {
        // _data = 1; // Compile error if uncommented.
        return ref reference;
    }
}

El método devuelve básicamente una referencia readonly junto con el miembro de la instancia (en este caso, un método) que es readonly (no puede modificar ningún campo de la instancia).

Especificación del lenguaje C#

Para obtener más información, consulte la Especificación del lenguaje C#. La especificación del lenguaje es la fuente definitiva de la sintaxis y el uso de C#.

También puede ver las propuestas de especificación del lenguaje:

Vea también