readonly (Referência de C#)
A palavra-chave readonly
é um modificador que pode ser usado em quatro contextos:
Em uma declaração de campo,
readonly
indica que a atribuição ao campo só pode ocorrer como parte da declaração ou em um construtor na mesma classe. Um campo readonly pode ser atribuído e reatribuído várias vezes na declaração de campo e no construtor.Um campo
readonly
não pode ser atribuído depois da saída do construtor. Essa regra tem implicações diferentes para tipos de valor e tipos de referência:- Como os tipos de valor contêm diretamente seus dados, um campo que é um tipo de valor
readonly
é imutável. - Como os tipos de referência contêm uma referência a seus dados, um campo que é um tipo de referência
readonly
deve sempre se referir ao mesmo objeto. Esse objeto pode não ser imutável. O modificadorreadonly
impede a substituição do valor do campo por uma instância diferente do tipo de referência. No entanto, o modificador não impede que dados da instância do campo sejam modificados por meio do campo somente leitura.
Aviso
Um tipo visível externamente que contém um campo somente leitura visível externamente que é um tipo de referência mutável pode ser uma vulnerabilidade de segurança e pode disparar um aviso CA2104 : “Não declare tipos de referência mutáveis somente leitura”.
- Como os tipos de valor contêm diretamente seus dados, um campo que é um tipo de valor
Em uma definição de tipo
readonly struct
,readonly
indica que o tipo de estrutura é imutável. Para saber mais, confira a seção Structreadonly
do artigo Tipos de struct.Em uma declaração de membro de instância dentro de um tipo de estrutura,
readonly
indica que um membro de instância não modifica o estado da estrutura. Para saber mais, confira a seção Membros de instânciareadonly
do artigo Tipos de struct.Em um retorno de método
ref readonly
, o modificadorreadonly
indica que o método retorna uma referência e que as gravações não são permitidas para essa referência.- Para declarar um
ref readonly
parâmetro a um método.
- Para declarar um
Exemplo de campo readonly
Neste exemplo, o valor do campo year
não pode ser alterado no método ChangeYear
, mesmo que tenha sido atribuído um valor no construtor de classe:
class Age
{
private readonly int _year;
Age(int year)
{
_year = year;
}
void ChangeYear()
{
//_year = 1967; // Compile error if uncommented.
}
}
Você pode atribuir um valor a um campo readonly
apenas nos seguintes contextos:
Quando a variável é inicializada na declaração, por exemplo:
public readonly int y = 5;
Em um construtor de instância da classe que contém a declaração de campo de instância.
No construtor estático da classe que contém a declaração do campo estático.
Esses contextos de construtor também são os únicos em que é válido passar um campo readonly
como um parâmetro out ou ref.
Observação
A palavra-chave readonly
é diferente da palavra-chave const. O campo const
pode ser inicializado apenas na declaração do campo. Um campo readonly
pode ser atribuído várias vezes na declaração do campo e em qualquer construtor. Portanto, campos readonly
podem ter valores diferentes dependendo do construtor usado. Além disso, enquanto um campo const
é uma constante em tempo de compilação, o campo readonly
pode ser usado para constantes de runtime, como no exemplo a seguir:
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
*/
}
No exemplo anterior, se você usar uma instrução semelhante ao seguinte exemplo:
p2.y = 66; // Error
você recebe a mensagem de erro do compilador:
Um campo somente leitura não pode ser atribuído (exceto em um construtor ou inicializador de variável)
Membros da instância ReadOnly
Você também pode usar o modificador readonly
para declarar que um membro de instância não modifica o estado de um struct.
public readonly double Sum()
{
return X + Y;
}
Observação
No caso de uma propriedade de leitura/gravação, você pode adicionar o modificador readonly
ao acessador get
. Alguns acessadores get
podem executar um cálculo e armazenar em cache o resultado, em vez de simplesmente retornar o valor de um campo privado. Adicionar o modificador readonly
ao acessador get
garante que o acessador get
não modifique o estado interno do objeto armazenando resultados em cache.
Você pode encontrar mais exemplos na seção membros da instância readonly
do artigo Tipos de estrutura.
Exemplo de retorno de readonly de ref
O modificador readonly
em um ref return
indica que a referência retornada não pode ser modificada. O exemplo a seguir retorna uma referência para a origem. Ele usa o modificador readonly
para indicar que os chamadores não podem modificar a origem:
private static readonly SamplePoint s_origin = new SamplePoint(0, 0, 0);
public static ref readonly SamplePoint Origin => ref s_origin;
O tipo retornado não precisa ser um readonly struct
. Qualquer tipo que possa ser retornado por ref
pode ser retornado por ref readonly
.
Exemplo de retorno readonly de referência readonly
Um ref readonly return
também pode ser usado com membros de instância readonly
em 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;
}
}
O método essencialmente retorna uma referência readonly
juntamente com o membro da instância (nesse caso, um método) sendo readonly
(não é capaz de modificar nenhum campo de instância).
Especificação da linguagem C#
Para obter mais informações, consulte a Especificação da linguagem C#. A especificação da linguagem é a fonte definitiva para a sintaxe e o uso de C#.
Você também pode ver as propostas de especificação de linguagem: