Pergunta

Qual é a diferença entre const e readonly e fazer você usar um sobre o outro?

Foi útil?

Solução

Para além da aparente diferença de

  • ter de declarar o valor no momento da definição de uma const VS readonly os valores podem ser calculados dinamicamente, mas precisam ser atribuído antes do construtor sai..depois que ele está congelado.
  • 'const são implicitamente static.Você usa um ClassName.ConstantName notação para acessá-los.

Há uma sutil diferença.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 referências AssemblyA e usa esses valores no código.Quando este é compilado,

  • no caso de o const valor, é como um encontrar-substituir o valor 2 é 'do forno' a AssemblyB's IL.Isso significa que, se amanhã eu vou atualizar I_CONST_VALUE 20 no futuro. AssemblyB ainda teria 2 até que eu recompilá-lo.
  • no caso de o readonly valor, é como um ref para um local de memória.O valor não é cozido em AssemblyB's IL.Isso significa que, se a localização de memória é atualizada, AssemblyB recebe o novo valor, sem recompilação.Por isso, se I_RO_VALUE é atualizado para 30, você só precisa construir AssemblyA.Todos os clientes não precisam ser recompilados.

Então, se você está confiante de que o valor da constante não alterar usar um const.

public const int CM_IN_A_METER = 100;

Mas se você tem uma constante que pode mudar (por exemplo,w.r.t.precisão)..ou quando em dúvida, use um readonly.

public readonly float PI = 3.14;

Atualização:Aku precisa obter uma menção pq ele apontou isso em primeiro lugar.Também eu preciso plug onde eu aprendi isso.. Eficaz C# - Wagner

Outras dicas

Há uma pegadinha com consts!Se você faz referência a uma constante a partir de outro conjunto, o seu valor será compilado direito na chamada assembleia.Dessa forma, quando você atualizar o constante no assembly referenciado isso não vai mudar, na chamada assembleia!

Constantes

  • Constantes são estáticos por padrão
  • Eles devem ter um valor de compilação em tempo (você pode ter e.g.3.14 * 2, mas não é possível chamar métodos)
  • Podem ser declaradas dentro de funções
  • São copiados para cada assembly que usa-los (cada assembly é uma cópia local dos valores)
  • Podem ser usados em atributos

Readonly campos de instância

  • Deve ter definido o valor, o momento em que sai construtor
  • São avaliados quando a instância é criada

Estática readonly campos

  • São avaliados quando a execução de código hits classe de referência (quando nova instância é criada ou de um método estático é executado)
  • Deve ter um valor avaliado pelo tempo que o construtor estático é feito
  • Não é recomendado colocar ThreadStaticAttribute sobre estes (estático de construtores será executado em uma thread só e defina o valor para o seu segmento;todos os outros threads terão este valor não inicializada)

Só para acrescentar, só de Leitura para tipos de referência torna-se uma referência readonly 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
  }
}

Isso explica.Resumo:const deve ser inicializada na declaração de tempo, só de leitura pode ser inicializado no construtor (e, portanto, têm um valor diferente, dependendo do construtor utilizado).

EDITAR:Ver Gishu da gotcha, acima, a sutil diferença

const:Não pode ser alterado em qualquer lugar.

readonly:Este valor pode ser alterado apenas no construtor.Não pode ser alterado nas suas funções normais.

Há uma pequena pegadinha com readonly.Uma leitura-campo pode ser ajustado várias vezes dentro do construtor(s).Mesmo se o valor é definido em dois diferentes encadeadas de construtores 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
    }
}

Uma constante membro é definido em tempo de compilação e não poderá ser alterada em tempo de execução.Constantes são declaradas como um campo, utilizando a const palavra-chave e deve ser inicializado como elas são declaradas.

public class MyClass
{
    public const double PI1 = 3.14159;
}

Um readonly membro é como uma constante que 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 ser capaz de ser inicializado como elas são declaradas.

public class MyClass1
{
     public readonly double PI2 = 3.14159;

     //or

     public readonly double PI3;

     public MyClass2()
     {
         PI3 = 3.14159;
     }
}

const

  • Eles não podem ser declarados como static (eles são implicitamente static)
  • O valor da constante é avaliada em tempo de compilação
  • constantes são inicializados na declaração apenas

somente leitura

  • Eles podem ser qualquer instância ou nível estático
  • O valor é avaliado em tempo de execução
  • só de leitura podem ser inicializadas na declaração ou por código no construtor

Uma constante é um tempo de compilação constante, considerando que somente leitura permite que um valor a ser calculado em tempo de execução e definido no construtor ou no campo do inicializador.Assim, uma 'constante' é sempre constante, mas 'só de leitura' é só de leitura, uma vez que é atribuída.

Eric Lippert a C# equipe tem mais informações sobre os diferentes tipos de imutabilidade

Aqui está outro link demonstrando como const não é a versão segura, ou relevantes para os tipos de referência.

Resumo:

  • O valor da sua constante de propriedade é definido em tempo de compilação e não poderá alterar em tempo de execução
  • Const não podem ser marcadas como static - a palavra-chave indica que eles são estáticos, ao contrário de somente leitura campos que podem.
  • Const não pode ser qualquer coisa, exceto o valor (primitiva) tipos de
  • A leitura de palavra-chave marca o campo como imutável.No entanto, a propriedade pode ser alterado dentro do construtor da classe
  • O só de leitura, só de palavras-chave também pode ser combinado com estáticos para torná-lo agir da mesma forma como uma constante (pelo menos na superfície).Há uma grande diferença quando você olha para o IL entre os dois
  • const campos marcados como "literal" em IL enquanto readonly "initonly"

Somente Leitura :O valor pode ser alterado através do Construtor em tempo de execução.Mas não através da Função de membro

Constante :Por defult estático.O valor não pode ser alterado a partir de qualquer lugar ( Ctor, de Função, de tempo de execução etc-onde)

Ainda outra pegadinha:readonly valores podem ser alterados por "desviante" código por meio de reflexão.

var fi = this.GetType()
             .BaseType
             .GetField("_someField", 
                       BindingFlags.Instance | BindingFlags.NonPublic);
fi.SetValue(this, 1);

Eu posso mudar a privada só de leitura de campo herdada em C# usando a reflexão?

Eu acredito que um const o valor é o mesmo para todos os objetos (e deve ser inicializada com um literal da expressão), considerando que readonly pode ser diferente para cada instanciação...

Um dos membros da equipe em nosso escritório fornecida a seguinte orientação sobre quando usar const, estático, e só de leitura:

  • Utilização const quando você tem uma variável de um tipo que você pode conhecer em tempo de execução (cadeia de caracteres literal, int, double, enumerações, etc.) que você deseja que todas as instâncias ou consumidores de uma classe para ter acesso ao local em que o valor não deve mudar.
  • Utilização estática quando você tiver dados que você deseja todas as instâncias ou consumidores de uma classe para ter acesso ao local em que o valor pode mudar.
  • Utilização estático, só de leitura quando você tem uma variável de um tipo que você não sabe em tempo de execução (objetos) que você deseja que todas as instâncias ou consumidores de uma classe para ter acesso ao local em que o valor não deve mudar.
  • Utilização somente leitura quando você tem uma instância de nível variável que você vai saber no momento da criação do objeto, que não devem mudar.

Uma nota final:um constante campo é estático, mas o inverso não é verdadeiro.

Ambos são constantes, mas uma constante, também está disponível em tempo de compilação.Isso significa que um aspecto a diferença é que você pode usar const variáveis como entrada para o atributo de construtores, mas não só de leitura variáveis.

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; }
  }
}

Variáveis marcadas const são pouco mais de rigidez #define macros, em tempo de compilação variável const referências são substituídos com o inline valores literais.Como consequência apenas determinados built-in primitivos tipos de valor pode ser usado dessa forma.Variáveis marcado como só de leitura pode ser definida, em um construtor, em tempo de execução e leitura-apenas-ness é aplicada durante o tempo de execução também.Há algumas menor custo de desempenho associado a este, mas isso significa que você pode usar readonly com qualquer tipo (mesmo tipos de referência).

Também, const variáveis são inerentemente estático, enquanto que a leitura de variáveis pode ser instância específica, se desejado.

Outro pegadinha.

Desde const realmente só funciona com tipos de dados básicos, se você quiser trabalhar com uma classe, você pode sentir-se "obrigado" a usar só de Leitura.No entanto, cuidado com a armadilha!ReadOnly significa que você não pode substituir o objeto com outro objeto (você não pode fazê-lo referir-se a outro objeto).Mas qualquer processo que tem uma referência para o objeto está livre para modificar os valores dentro o objeto!

Portanto, não pode ser confundido, em pensar que só de Leitura implica um usuário não pode mudar as coisas.Não é simples de sintaxe em C# para evitar uma instanciação de uma classe de terem seus valores internos alterado (até onde eu sei).

Não há diferença notável entre constante e readonly campos C#.Net

const é por padrão estático e precisa ser inicializado com valor constante, que não pode ser modificado mais tarde.Alteração de valor não é permitido em construtores, também.Ele não pode ser usado com todos os tipos de dados.Para o ex - DateTime.Ele 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

só de leitura pode ser declarado como estático, mas não é necessário.Não há necessidade de inicializar no momento da declaração.O seu valor pode ser atribuído ou alterado usando o construtor.Então, ele dá uma vantagem quando usado como instância de membro de classe.Dois diferentes instanciação pode ter valor diferente de leitura de campo.Para o ex -

class A
{
    public readonly int Id;

    public A(int i)
    {
        Id = i;
    }
}

Em seguida, readonly campo pode ser inicializado com o instant valores específicos, como segue:

A objOne = new A(5);
A objTwo = new A(10);

Aqui, por exemplo, objOne terá valor do campo readonly como 5 e objTwo tem 10.O que não é possível usando const.

Um constante vai ser compilado para o consumidor como um valor literal, enquanto a seqüência de caracteres estática irá servir como uma referência para o valor definido.

Como exercício, tente criar uma biblioteca externa e consumi-lo em um aplicativo de console e, em seguida, alterar os valores na biblioteca e recompilá-lo (sem recompilar o consumidor programa), gota a DLL para o diretório e execute o EXE manualmente, você deve encontrar que a constante de seqüência de caracteres não muda.

Constante

Precisamos fornecer o valor para o campo const quando ele é definido.O compilador, em seguida, salva o constante do valor no conjunto de metadados.Isso significa que uma constante só pode ser definida para o tipo primitivo como boolean, char, byte, e assim por diante.Constantes são sempre considerados estáticos membros, não membros de instância.

Somente leitura

Readonly campos só pode ser resolvida 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 for declarado.A verificação é feita pelo compilador que readonly campos não são escritas por qualquer outro método que o construtor.

Mais sobre explicado aqui neste artigo

CONST

  1. palavra-chave const podem ser aplicadas a campos ou variáveis locais
  2. Devemos atribuir const campo no momento da declaração
  3. Não há Memória Alocada Porque const valor é incorporado no código IL si após a compilação.É como localizar todas as ocorrências da variável const e substituir pelo seu valor.Assim, o código IL após a compilação terá valores hard-coded no lugar de const variáveis
  4. Constante em C# são por padrão estático.
  5. O valor é constante para todos os objetos
  6. Há dll de controle de versão problema - Isso significa que sempre que alterar um público const variável ou propriedade , (Na verdade, ele não deve ser alterado, teoricamente), qualquer outra dll ou montagem que utiliza esta variável tem de ser re-construída
  7. Só C# tipos internos podem ser declarados como constante
  8. Const campo não pode ser passado como ref ou out parâmetro

Somente leitura

  1. readonly palavra-chave aplica-se apenas aos campos não variáveis locais
  2. Podemos atribuir readonly campo no momento da declaração ou no construtor,não em todos os outros métodos.
  3. dinâmica de memória alocada para só de leitura campos e nós podemos obter o valor em tempo de execução.
  4. Readonly pertence ao objeto criado para acessados apenas por meio de instância da classe.Para torná-lo membro de classe precisamos adicionar palavra-chave estática antes de só de leitura.
  5. O valor pode ser diferente dependendo do construtor usado (como pertence ao objeto da classe)
  6. Se você declarar um não-tipos primitivos (tipo de referência) como somente leitura, apenas de referência é imutável, não o objeto que ele contém.
  7. Uma vez que o valor é obtido em tempo de execução, não há nenhuma dll de controle de versão problema com readonly campos/ propriedades.
  8. Podemos passar readonly campo ref ou out parâmetros no construtor de contexto.

Principalmente;você pode atribuir um valor a uma estática readonly campo para um não-valor constante em tempo de execução, considerando que uma constante tem de ser atribuído um valor constante.

Um const tem que ser hard-coded, onde, como readonly pode ser definido no construtor da classe.

Const e só de leitura são semelhantes, mas eles não são exatamente os mesmos.Um constante campo é um tempo de compilação constante, ou seja, que valor pode ser calculado em tempo de compilação.Um readonly campo permite adicionais cenários em que o código deve ser executado durante a construção do tipo.Após a construção, um readonly campo não pode ser alterado.

Por exemplo, const membros podem ser usados para definir os membros como:

struct Test
{
    public const double Pi = 3.14;
    public const int Zero = 0;
}

desde valores como 3.14 e 0 são constantes de tempo de compilação.No entanto, considere o caso onde você define um tipo e deseja fornecer alguns pré-fab instâncias do mesmo.E. g., você pode querer definir uma classe de Cor e fornecer "constantes" comuns cores como Preto, Branco, etc.Não é possível fazer isso com const membros, como a mão direita lados não são constantes de tempo de compilação.Um poderia fazer isso com regular membros estáticos:

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 então não há nada para manter um cliente de Cor a partir de esterco com ele, talvez trocando o Preto-e-Branco de valores.Escusado será dizer que este poderia causar consternação para outros clientes da classe de Cor.O "só de leitura" recurso de endereços esse cenário.Por simplesmente introduzir a leitura de palavra-chave em declarações, preservamos a inicialização flexíveis evitando o código do cliente de fuçando.

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 const membros são sempre estáticos, enquanto que uma leitura membro pode ser estática ou não, apenas como um campo regular.

É possível usar uma única palavra-chave para estes dois propósitos, mas isso leva a um controle de versão de problemas ou problemas de desempenho.Suponha por um momento que temos usado uma única palavra-chave para esta (const) e um desenvolvedor escreveu:

public class A
{
    public static const C = 0;
}

e um programador escreveu o código que contou com:

public class B
{
    static void Main() {
        Console.WriteLine(A.C);
    }
}

Agora, o código que é gerado confiar no fato de que A. C é um tempo de compilação constante?I. e., pode o uso de A. C simplesmente substituído pelo valor 0?Se você disser "sim" para isso, então isso significa que o desenvolvedor de Um não pode mudar a forma que A. C é inicializado -- esta amarra as mãos do desenvolvedor de Um sem permissão.Se você disser "não" a esta pergunta, em seguida, uma importante otimização é desperdiçada.Talvez o autor de A é positivo que A. C será sempre zero.O uso de ambos const e somente leitura permite que o desenvolvedor de Um para especificar a intenção.Isso contribui para um melhor controle de versão de comportamento e também um melhor desempenho.

ReadOnly :O valor será inicializada apenas uma vez a partir do construtor da classe.
const:pode ser inicializado em qualquer função, mas apenas uma vez

A diferença é que o valor de um estático readonly campo é definido em tempo de execução, então ele pode ter um valor diferente para diferentes execuções do programa.No entanto, o valor de uma constante de campo é definido como um tempo de compilação constante.

Lembre-se:Para tipos de referência, em ambos os casos (estático e instância), a leitura modificador apenas impede a atribuição de uma nova referência para o campo.Especificamente, ele não tornar imutável o objeto apontado pela referência.

Para obter detalhes, consulte a C# Perguntas mais Frequentes sobre este tema:http://blogs.msdn.com/csharpfaq/archive/2004/12/03/274791.aspx

Constante as variáveis são declaradas e inicializadas em tempo de compilação.O valor não pode ser alterado depois de alas.Variáveis de leitura apenas serão inicializados somente a partir do construtor Estático da classe.Somente leitura só é usado quando queremos atribuir o valor em tempo de execução.

Uma coisa a acrescentar ao que já disse acima.Se você tem um assembly que contém um readonly valor (e.g.readonly MaxFooCount = 4;), você pode alterar o valor de chamar assembleias ver pelo envio de uma nova versão do assembly com um valor diferente (por exemplo,readonly MaxFooCount = 5;)

Mas com uma constante, seria dobrado para o chamador do código quando o chamador foi compilado.

Se você chegou a este nível de C# proficiência, você está pronto para Wagner livro, Eficaz C#:50 Maneiras Específicas para Melhorar o Seu C# Que responde a essa questão em detalhes, (e 49 outras coisas).

A principal diferença é que a Constante é o equivalente C de #DEFINE.O número, literalmente, fica substituído um-la pré-compilador.Readonly, na verdade, é tratada como uma variável.

Esta distinção é especialmente relevante quando você tem Um Projeto, dependendo de um Público constante do Projeto B.Suponha que o público em constante mudança.Agora a sua escolha de const/readonly terá impacto sobre o comportamento no projeto:

Const:projeto de Um não pegar o novo valor (a menos que seja recompilado com o novo const, é claro), porque ele foi compilado com as constantes subtituted em.

ReadOnly:Um projeto é sempre pedir projeto B é o valor da variável, então ele vai pegar o novo valor para o público constante em B.

Honestamente, eu recomendo que você use somente leitura para quase tudo, exceto verdadeiramente universal constantes ( por exemplo,Pi, Inches_To_Centimeters).Para qualquer coisa que pudesse mudar, eu digo que uso só de leitura.

Espero que isso ajude, Alan.

Em palavras simples Const é tempo de compilação e o acesso somente leitura é o tempo de execução.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top