Qual é a diferença entre const
e readonly
em c #?
Quando você usaria um sobre o outro?
Qual é a diferença entre const
e readonly
em c #?
Quando você usaria um sobre o outro?
Respostas:
Além da aparente diferença de
const
VS readonly
pode ser calculado dinamicamente, mas precisa ser atribuído antes que o construtor saia .. depois disso, ele é congelado.static
. Você usa uma ClassName.ConstantName
notação para acessá-los.Há uma diferença sutil. Considere uma classe definida em AssemblyA
.
public class Const_V_Readonly
{
public const int I_CONST_VALUE = 2;
public readonly int I_RO_VALUE;
public Const_V_Readonly()
{
I_RO_VALUE = 3;
}
}
AssemblyB
referencia AssemblyA
e usa esses valores no código. Quando isso é compilado,
const
valor, é como uma substituição de localização, o valor 2 é 'incorporado à AssemblyB
' IL. Isso significa que, se amanhã eu atualizar I_CONST_VALUE
para 20 no futuro. AssemblyB
ainda teria 2 até eu recompilar .readonly
valor, é como um ref
local de memória. O valor não está inserido AssemblyB
na IL. Isso significa que, se o local da memória for atualizado, AssemblyB
obtém o novo valor sem recompilação. Portanto, se I_RO_VALUE
for atualizado para 30, você precisará criar apenas AssemblyA
. Todos os clientes não precisam ser recompilados.Portanto, se você estiver confiante de que o valor da constante não mudará, use a const
.
public const int CM_IN_A_METER = 100;
Mas se você tem uma constante que pode mudar (por exemplo, precisão de escrita) .. ou em caso de dúvida, use a readonly
.
public readonly float PI = 3.14;
Atualização: Aku precisa fazer uma menção porque ele apontou isso primeiro. Também preciso conectar onde aprendi isso. C # eficaz - Bill Wagner
static
ponto parece ser o ponto mais importante e útil -consts are implicitly static
readonly
variáveis podem ser alteradas fora do construtor (reflexão). É apenas o compilador que tenta impedir você de modificar o var fora do construtor.
readonly
variáveis @ mini-me não podem ser alteradas após a conclusão do construtor, mesmo através da reflexão. O tempo de execução não impõe isso. O tempo de execução também acontece para não impor que você não mudar string.Empty
para "Hello, world!"
, mas eu ainda não diria que isso faz string.Empty
modificáveis, ou que o código não deve assumir que string.Empty
será sempre uma cadeia de comprimento zero.
Há uma pegadinha com consts! Se você referenciar uma constante de outra montagem, seu valor será compilado diretamente na montagem de chamada. Dessa forma, quando você atualiza a constante na montagem referenciada, ela não muda na montagem de chamada!
Apenas para adicionar, o ReadOnly somente para tipos de referência torna a referência somente leitura, não os valores. Por exemplo:
public class Const_V_Readonly
{
public const int I_CONST_VALUE = 2;
public readonly char[] I_RO_VALUE = new Char[]{'a', 'b', 'c'};
public UpdateReadonly()
{
I_RO_VALUE[0] = 'V'; //perfectly legal and will update the value
I_RO_VALUE = new char[]{'V'}; //will cause compiler error
}
}
string
que você possa usar como constante?
const
com tipos de referência diferentes de sequência, mas a constante pode ter apenas o valor null
.
Isso explica isso . Resumo: const deve ser inicializado no momento da declaração, somente leitura pode ser inicializado no construtor (e, portanto, ter um valor diferente, dependendo do construtor usado).
EDIT: Veja a pegadinha de Gishu acima para a diferença sutil
Há uma pequena pegadinha com somente leitura. Um campo somente leitura pode ser definido várias vezes no (s) construtor (es). Mesmo que o valor seja definido em dois construtores encadeados diferentes, ele ainda é permitido.
public class Sample {
private readonly string ro;
public Sample() {
ro = "set";
}
public Sample(string value) : this() {
ro = value; // this works even though it was set in the no-arg ctor
}
}
Um membro constante é definido no tempo de compilação e não pode ser alterado no tempo de execução. As constantes são declaradas como um campo, usando a const
palavra - chave e devem ser inicializadas conforme são declaradas.
public class MyClass
{
public const double PI1 = 3.14159;
}
Um readonly
membro é como uma constante, pois representa um valor imutável. A diferença é que um readonly
membro pode ser inicializado em tempo de execução, em um construtor, além de poder ser inicializado conforme declarado.
public class MyClass1
{
public readonly double PI2 = 3.14159;
//or
public readonly double PI3;
public MyClass2()
{
PI3 = 3.14159;
}
}
const
static
(eles são implicitamente estáticos)somente leitura
static const int i = 0;
const
declarações não podem ser feitas dentro de métodos?
Uma const é uma constante em tempo de compilação, enquanto que somente leitura permite que um valor seja calculado em tempo de execução e definido no construtor ou inicializador de campo. Portanto, uma 'const' é sempre constante, mas 'readonly' é somente leitura quando é atribuída.
Eric Lippert, da equipe C #, tem mais informações sobre diferentes tipos de imutabilidade
Aqui está outro link demonstra como const não é uma versão segura ou relevante para tipos de referência.
Resumo :
Somente leitura : o valor pode ser alterado através do Ctor em tempo de execução. Mas não através da função membro
Constante : Por padrão estático. O valor não pode ser alterado de qualquer lugar (Ctor, Função, tempo de execução etc, não-onde)
Ainda outro problema: valores somente leitura podem ser alterados por código "desonesto" via reflexão.
var fi = this.GetType()
.BaseType
.GetField("_someField",
BindingFlags.Instance | BindingFlags.NonPublic);
fi.SetValue(this, 1);
Posso alterar um campo herdado privado somente de leitura em C # usando reflexão?
Eu acredito que um const
valor é o mesmo para todos os objetos (e deve ser inicializado com uma expressão literal), enquanto readonly
pode ser diferente para cada instanciação ...
Um dos membros da equipe em nosso escritório forneceu as seguintes orientações sobre quando usar const, static e readonly:
Uma nota final: um campo const é estático, mas o inverso não é verdadeiro.
Ambos são constantes, mas uma const está disponível também em tempo de compilação. Isso significa que um aspecto da diferença é que você pode usar variáveis const como entrada para atribuir construtores, mas não variáveis somente leitura.
Exemplo:
public static class Text {
public const string ConstDescription = "This can be used.";
public readonly static string ReadonlyDescription = "Cannot be used.";
}
public class Foo
{
[Description(Text.ConstDescription)]
public int BarThatBuilds {
{ get; set; }
}
[Description(Text.ReadOnlyDescription)]
public int BarThatDoesNotBuild {
{ get; set; }
}
}
quando usar const
oureadonly
const
readonly
App.config
, mas, uma vez inicializada, não pode ser alteradaAs variáveis marcadas como const são pouco mais do que macros #define fortemente tipadas; no tempo de compilação, as referências às variáveis const são substituídas por valores literais embutidos. Como conseqüência, apenas certos tipos de valores primitivos internos podem ser usados dessa maneira. As variáveis marcadas como somente leitura podem ser definidas, em um construtor, no tempo de execução e sua somente leitura é imposta também durante o tempo de execução. Existe um custo menor de desempenho associado a isso, mas significa que você pode usar somente leitura com qualquer tipo (mesmo tipos de referência).
Além disso, variáveis const são inerentemente estáticas, enquanto variáveis readonly podem ser específicas da instância, se desejado.
Outra pegadinha .
Como const realmente funciona apenas com tipos de dados básicos, se você deseja trabalhar com uma classe, pode se sentir "forçado" a usar o ReadOnly. No entanto, cuidado com a armadilha! ReadOnly significa que você não pode substituir o objeto por outro (você não pode fazer com que ele se refira a outro objeto). Mas qualquer processo que tenha uma referência ao objeto é livre para modificar os valores dentro do objeto!
Portanto, não se confunda ao pensar que o ReadOnly implica que um usuário não pode mudar as coisas. Não há sintaxe simples em C # para impedir que uma instanciação de uma classe altere seus valores internos (tanto quanto eu sei).
Há uma diferença notável entre os campos const e somente leitura em C # .Net
const é, por padrão, estático e precisa ser inicializado com valor constante, que não pode ser modificado posteriormente. Mudança de valor também não é permitida em construtores. Não pode ser usado com todos os tipos de dados. Por ex DateTime. Não pode ser usado com o tipo de dados DateTime.
public const DateTime dt = DateTime.Today; //throws compilation error
public const string Name = string.Empty; //throws compilation error
public readonly string Name = string.Empty; //No error, legal
readonly pode ser declarado como estático, mas não necessário. Não há necessidade de inicializar no momento da declaração. Seu valor pode ser atribuído ou alterado usando o construtor. Portanto, oferece vantagem quando usado como membro da classe de instância. Duas instâncias diferentes podem ter um valor diferente do campo somente leitura. Por ex -
class A
{
public readonly int Id;
public A(int i)
{
Id = i;
}
}
Em seguida, o campo somente leitura pode ser inicializado com valores específicos instantâneos, da seguinte maneira:
A objOne = new A(5);
A objTwo = new A(10);
Aqui, a instância objOne terá o valor do campo somente leitura como 5 e objTwo tem 10. O que não é possível usando const.
Uma constante será compilada no consumidor como um valor literal, enquanto a sequência estática servirá como uma referência ao valor definido.
Como exercício, tente criar uma biblioteca externa e consumi-la em um aplicativo de console, altere os valores na biblioteca e recompile-a (sem recompilar o programa do consumidor), solte a DLL no diretório e execute o EXE manualmente, você deve encontrar que a cadeia constante não muda.
Constante
Precisamos fornecer o valor para o campo const quando ele é definido. O compilador salva o valor da constante nos metadados do assembly. Isso significa que uma constante pode ser definida apenas para o tipo primitivo, como booleano, char, byte e assim por diante. As constantes são sempre consideradas membros estáticos, não membros da instância.
Somente leitura
Os campos somente leitura podem ser resolvidos em tempo de execução. Isso significa que podemos definir um valor para um valor usando o construtor para o tipo em que o campo é declarado. A verificação é feita pelo compilador de que os campos somente leitura não são gravados por nenhum método que não seja o construtor.
Mais sobre os dois explicados aqui neste artigo
Const e somente leitura são semelhantes, mas não são exatamente iguais. Um campo const é uma constante em tempo de compilação, o que significa que esse valor pode ser calculado em tempo de compilação. Um campo somente leitura permite cenários adicionais em que algum código deve ser executado durante a construção do tipo. Após a construção, um campo somente leitura não pode ser alterado.
Por exemplo, membros const podem ser usados para definir membros como:
struct Test
{
public const double Pi = 3.14;
public const int Zero = 0;
}
já que valores como 3,14 e 0 são constantes em tempo de compilação. No entanto, considere o caso em que você define um tipo e deseja fornecer algumas instâncias pré-fabricadas. Por exemplo, você pode definir uma classe Color e fornecer "constantes" para cores comuns, como preto, branco etc. Não é possível fazer isso com membros const, pois o lado direito não é uma constante em tempo de compilação. Pode-se fazer isso com membros estáticos regulares:
public class Color
{
public static Color Black = new Color(0, 0, 0);
public static Color White = new Color(255, 255, 255);
public static Color Red = new Color(255, 0, 0);
public static Color Green = new Color(0, 255, 0);
public static Color Blue = new Color(0, 0, 255);
private byte red, green, blue;
public Color(byte r, byte g, byte b) {
red = r;
green = g;
blue = b;
}
}
mas não há nada que impeça um cliente da Color de trocá-lo, talvez trocando os valores de preto e branco. Escusado será dizer que isso causaria consternação para outros clientes da classe Color. O recurso "somente leitura" aborda esse cenário. Simplesmente introduzindo a palavra-chave readonly nas declarações, preservamos a inicialização flexível e impedimos que o código do cliente mexa.
public class Color
{
public static readonly Color Black = new Color(0, 0, 0);
public static readonly Color White = new Color(255, 255, 255);
public static readonly Color Red = new Color(255, 0, 0);
public static readonly Color Green = new Color(0, 255, 0);
public static readonly Color Blue = new Color(0, 0, 255);
private byte red, green, blue;
public Color(byte r, byte g, byte b) {
red = r;
green = g;
blue = b;
}
}
É interessante notar que os membros const são sempre estáticos, enquanto um membro somente leitura pode ser estático ou não, assim como um campo regular.
É possível usar uma única palavra-chave para esses dois propósitos, mas isso leva a problemas de versão ou de desempenho. Suponhamos por um momento que usamos uma única palavra-chave para isso (const) e um desenvolvedor escreveu:
public class A
{
public static const C = 0;
}
e um desenvolvedor diferente escreveu um código que contava com A:
public class B
{
static void Main() {
Console.WriteLine(A.C);
}
}
Agora, o código gerado pode confiar no fato de que o AC é uma constante em tempo de compilação? Ou seja, o uso de AC pode simplesmente ser substituído pelo valor 0? Se você disser "sim" a isso, isso significa que o desenvolvedor de A não pode mudar a maneira como o CA é inicializado - isso amarra as mãos do desenvolvedor de A sem permissão. Se você disser "não" a esta pergunta, uma otimização importante será perdida. Talvez o autor de A tenha certeza de que AC sempre será zero. O uso de const e readonly permite que o desenvolvedor de A especifique a intenção. Isso contribui para um melhor comportamento de versão e também um melhor desempenho.
A diferença é que o valor de um campo estático somente leitura é definido em tempo de execução, para que ele possa ter um valor diferente para diferentes execuções do programa. No entanto, o valor de um campo const é definido como uma constante de tempo de compilação.
Lembre-se: Para tipos de referência, nos dois casos (estático e instância), o modificador somente leitura impede que você atribua uma nova referência ao campo. Especificamente, não torna imutável o objeto apontado pela referência.
Para obter detalhes, consulte as Perguntas freqüentes em C # sobre este tópico: http://blogs.msdn.com/csharpfaq/archive/2004/12/03/274791.aspx
Variáveis constantes são declaradas e inicializadas em tempo de compilação. O valor não pode ser alterado após as alas. As variáveis somente leitura serão inicializadas apenas no construtor Static da classe. Somente leitura é usado apenas quando queremos atribuir o valor em tempo de execução.
Const : valor constante absoluto durante o tempo de vida da aplicação.
Somente leitura : pode ser alterado em tempo de execução.
Uma coisa a acrescentar ao que as pessoas disseram acima. Se você tiver uma montagem contendo um valor somente leitura (por exemplo, somente MaxFooCount = 4;), poderá alterar o valor que os assemblies chamadores veem enviando uma nova versão dessa montagem com um valor diferente (por exemplo, somente MaxFooCount = 5;)
Mas com uma const, seria dobrada no código do chamador quando o compilador fosse compilado.
Se você atingiu esse nível de proficiência em C #, está pronto para o livro de Bill Wagner, C # efetivo: 50 maneiras específicas de melhorar seu C # O que responde a essa pergunta em detalhes (e 49 outras coisas).