QUAL A DIFEREN?A ENTRE READONLY E CONST

KELLY 17/02/2016 13:15:23
#457775
Olá amigos, bom dia!

Estou com uma grande dificuldade em saber a diferença entre READONLY e CONST. Vi em um artigos que READONLY pode receber diferentes valores em tempo de execução, inclusive receber resultados de uma função. Mas pelos testes que estou fazendo, ele está mais parecendo uma CONST, não está aceitando nenhum valor em tempo de execução, retornando o seguinte erro:

A readonly field cannot be assigned to (except in a constructor or a variable initializer)

Então qual a diferença entre o READONLY e CONST?

JONATHANSTECKER 17/02/2016 14:17:40
#457785
Olá Kelly,

Em resumo, as Contants só podem receber valor no momento em que ela for declarada, enquanto Readonly pode receber valor em tempo de execução ou via construtor.
DS2T 17/02/2016 14:32:42
#457786
Eu nunca tinha parado pra pensar na semelhança do ReadOnly com o Const atá agora. Mas existem algumas diferenças substanciais entre as duas.

A primeira é que Const é usado para dados primitivos. Você não pode setar uma instância de um objeto como constante, por exemplo.
A segunda é que o ReadOnly é um modificador de uma propriedade usado pra você poder manipular a propriedade somente no próprio escopo da classe.

Note que o ReadOnly está intimamente ligado à propriedade da classe, enquanto o Const é usado para constantes quaisquer.
Exemplo do uso de Const: Códigos ASCII das teclas. Keys.Return, Keys.Backspace... são todos constantes.

O ReadOnly já é usado em classes que o usuário da classe não pode modificar externamente.

Se eu crio uma classe chamada Pessoa. Essa classe tem uma propriedade ReadOnly chamada Respirando. E tem dois métodos chamados Morreu(), Viveu().

Quando você chama o método Morreu a pessoa para de respirar (A propriedade Respirando vai pra False).
Quando você chama o método Viveu a pessoa continua a respirar (A propriedade Respirando vai pra True).

Repare que quem usar a classe Pessoa, não pode setar diretamente a propriedade Respirando. Apenas pegar o valor dela.

Dentro do classe pessoa, você não pode simplesmente setar a propriedade (Senão vai dar o erro que mencionou). Você precisa de uma variável de suporte para isso. Exemplo:

Public Class Pessoa
private _respirando As Boolean = true
Public Sub Morreu()
_respirando = false
End Sub

Public Sub Viveu()
_respirando = true
End Sub

Public ReadOnly Property Respirando AS Boolean
Get
return _respirando
End Get
End Property

End Class


Pode ter algum errinho, porque fiz sem o visual studio... mas a ideia é essa.
KELLY 18/02/2016 19:07:17
#457858
DS2T então quer dizer que o ReadOnly eu posso alterar em tempo real?
KERPLUNK 18/02/2016 19:19:41
#457860
Vamos lá: Propriedades podem conter variáveis internas para controle. Essas variáveis internas podem ser alteradas em métodos ou eventos de dentro da classe mas não na instância, bem como o DS2T falou.
KELLY 22/02/2016 12:28:37
#458029
Oi KERPLUNK, então pelo que entendi na explicações sua e do DST2, as READONLY apesar de ter o nome de LEITURA, eu também posso alterar o seu valor desde que seja de métodos ou eventos da própria classe onde foi definido este campo, correto? Já as CONST, pelos testes que eu viz e pesquisei, elas não podem ter o seu valor alterado e também são estáticas, como se eu tivesse colocado a palavra reservada STATIC.

Eu só não entendo o porquê que eu não consigo alterar o valor do campo definido como READONLY que está na própria classe e que insiste em me retornar o erro:
A readonly field cannot be assigned to (except in a constructor or a variable initializer)

OCELOT 22/02/2016 13:31:50
#458032
Resposta escolhida
Primeiro de tudo temos que entrar em um detalhe que existe uma diferença entre o VB.Net e o C#, o DS2T respondeu como exemplo as propriedades ReadOnly, veja que no C# este tipo de propriedade não usa o keyword [Ô]readonly[Ô], você simplesmente declara ela só com o get, então eu diria que não vem ao caso.

Já os campos (variáveis declaradas dentro de classes) que forem marcadas como readonly no C# não podem ter o seu valor modificado, você vai apenas definir o valor inicial, que pode ser feito direto na declaração, do tipo
public readonly int MeuValor = 100;

Ou em um contrutor, e é ai que vem o fato que este valor pode mudar, mas apenas na hora em que a classe for instanciada, por exemplo
public class MinhaClasse
{
public readonly int MeuValor;

public MinhaClasse(int Valor)
{
MeuValor = Valor;
}
}

Desta forma eu posso ter várias instâncias do MinhaClasse cada uma com uma valor diferente, mas eu não posso modificar este valor em nenhum outro lugar.

Variáveis readonly vão funciona basicamente como uma variável normal porém que não pode ter o valor modificado. Digo isso pois o valor desta variável é sempre acessado da mesma forma que qualquer outra variável, o que é diferente de uma constante.

Quando você usa uma constante, no momento da compilação o valor desta constante é incluído no código, como se você tivesse digitado ele ali, por exemplo
class Program
{
public const int A = 10;
public const int B = 20;

public const string C = [Ô]teste[Ô];

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

Se você compilar este código e examinar o IL dele em algum programa de engenharia reversa, como por exemplo o ILSpy você vai ver que as constantes existem na classe Program, porém examinando o método Main você vai ver que elas não são usadas, e no lugar delas existe os valores direto, e mais ainda, como estes valores são constantes, nunca mudam, o compilador pode otimizar e na linha em que fazemos o [Ô]A + B[Ô] o compilador vai colocar direto o valor [Ô]30[Ô], pois não existe como ser outro valor.

Isso é algo importante de se saber pois existe um cenário em que isso pode causar um comportamento estranho em seu programa.

Digamos que você tenha uma DLL [Ô]A[Ô] e nela tem uma constante [Ô]C[Ô] com valor igual a [Ô]10[Ô], você referencia então essa DLL no seu programa [Ô]B[Ô] e usa esta constante. Um dia você precisa mudar o valor desta constante para [Ô]11[Ô] e então recompila a DLL, como não teve nenhuma outra mudança você pensa que não precisa recompilar o executável [Ô]B[Ô] e só troca a DLL, então você percebe que o valor está errado, pois o programa [Ô]B[Ô] que não foi recompilado continua usando o valor antigo, pois este valor foi incluído no código dele na hora da compilação.
KELLY 24/02/2016 13:48:27
#458159
Boa tarde OCELOT! Achei interessante a explicação usando a Linguagem Intermediária. Vou passar a analisar os códigos com esse recurso que eu usava tão pouco.

Eu gostei das explicações que postou, vai me ajudar bastante. Muito legal também as explicações KERPLUNK, DS2T e JONATHANSTECKER.
Por incrível que pareça eu eu fiz um curso de C# com um instrutor que já saiu até no jornal há alguns anos atrás e ele era MVP e tinha várias certificações Microsoft e não soube explicar essa diferença. Todos da turma começaram a pesquisar porque ele falou que não sabia respontar e vocês conseguiram responder tranquilo e de maneira até melhor do que as que eu pesquisei na internet e não conseguiram esclarecer a minha dúvida.

Obrigada a todos!

Tópico encerrado , respostas não são mais permitidas