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 modificadorreadonly
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".
- Debido a que los tipos de valor contienen directamente sus datos, un campo que es un tipo de valor
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 structreadonly
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 instanciareadonly
del artículo Tipos de estructura.En una devolución del método
ref readonly
, el modificadorreadonly
indica que el método devuelve una referencia y las operaciones de escritura no se permiten en esa referencia.- Para declarar un parámetro
ref readonly
en un método.
- Para declarar un parámetro
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 readonly
del 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: