Ter um debate amigável com um colega de trabalho sobre isso. Temos algumas ideias sobre isso, mas quer saber o que a multidão do SO pensa sobre isso?
Ter um debate amigável com um colega de trabalho sobre isso. Temos algumas ideias sobre isso, mas quer saber o que a multidão do SO pensa sobre isso?
Respostas:
Um dos motivos é que não há suporte CLR para um local somente leitura. Readonly é traduzido no opcode initonly CLR / CLI. Este sinalizador só pode ser aplicado a campos e não tem significado para um local. Na verdade, aplicá-lo a um local provavelmente produzirá um código não verificável.
Isso não significa que C # não possa fazer isso. Mas daria dois significados diferentes para a mesma construção de linguagem. A versão para locais não teria mapeamento equivalente de CLR.
readonlypalavra-chave para os campos precisa ser suportada pela CLI porque seu efeito é visível para outros assemblies. Significa apenas que a variável tem apenas uma atribuição no método em tempo de compilação.
const(que em C ++ é mais parecido com C # do readonlyque com C # const, embora possa desempenhar ambas as funções). Ainda assim, C ++ oferece suporte constpara variável automática local. Conseqüentemente, a falta de suporte CLR para um C # readonlypara variável local é irrelevante.
usinge outestão fazendo exatamente isso e o mundo não entrou em colapso.
Acho que é um julgamento pobre por parte dos arquitetos C #. o modificador somente leitura em variáveis locais ajuda a manter a correção do programa (assim como afirma) e pode ajudar potencialmente o compilador a otimizar o código (pelo menos no caso de outras linguagens). O fato de não ser permitido no C # agora é outro argumento de que alguns dos "recursos" do C # são meramente uma imposição do estilo de codificação pessoal de seus criadores.
Respondendo à resposta de Jared, provavelmente teria que ser apenas um recurso de tempo de compilação - o compilador iria proibir você de escrever na variável após a declaração inicial (que teria que incluir uma atribuição).
Posso ver valor nisso? Potencialmente - mas não muito, para ser honesto. Se você não puder dizer facilmente se uma variável será ou não atribuída em outro lugar no método, então seu método é muito longo.
Pelo que vale a pena, Java tem esse recurso (usando o finalmodificador) e muito raramente o vi usado, exceto nos casos em que tem que ser usado para permitir que a variável seja capturada por uma classe interna anônima - e onde ela está usado, dá-me a impressão de desordem em vez de informação útil.
readonly/ finalvalores de variáveis com suas palavras val- varchave e . No código Scala, os locais valsão usados com muita frequência (e são, de fato, preferidos aos locais var). Suspeito que os principais motivos pelos quais o finalmodificador não é usado com mais frequência em Java são a) desordem eb) preguiça.
readonlynão seria muito importante. Por outro lado, para variáveis locais que são usadas em encerramentos, readonlyem muitos casos deixariam o compilador gerar um código mais eficiente. Atualmente, quando a execução entra em um bloco que contém um fechamento, o compilador deve criar um novo objeto heap para as variáveis fechadas, mesmo se nenhum código que usaria o fechamento seja executado . Se uma variável fosse somente leitura, o código fora do encerramento poderia usar uma variável normal; apenas quando um delegado é criado para o encerramento ...
Uma proposta somente leitura de locais e parâmetros para foi brevemente discutida pela equipe de design do C # 7. De C # Design Meeting Notes para 21 de janeiro de 2015 :
Parâmetros e locais podem ser capturados por lambdas e, portanto, acessados simultaneamente, mas não há como protegê-los de problemas de estado mútuo compartilhado: eles não podem ser somente leitura.
Em geral, a maioria dos parâmetros e muitos locais nunca devem ser atribuídos depois de obterem seu valor inicial. Permitir somente leitura neles expressaria essa intenção claramente.
Um problema é que esse recurso pode ser um "incômodo atraente". Considerando que a "coisa certa" a fazer quase sempre seria tornar os parâmetros e locais somente leitura, isso desordenaria o código significativamente.
Uma ideia para aliviar parcialmente isso é permitir que a combinação somente leitura var em uma variável local seja contraída para val ou algo curto assim. De maneira mais geral, poderíamos tentar simplesmente pensar em uma palavra-chave mais curta do que a somente leitura estabelecida para expressar o somente leitura.
A discussão continua no repositório C # Language Design. Vote para mostrar seu apoio. https://github.com/dotnet/csharplang/issues/188
É um descuido para o designer da linguagem c #. F # tem a palavra-chave val e é baseada no CLR. Não há razão para que C # não tenha o mesmo recurso de linguagem.
Eu era aquele colega de trabalho e não era amigável! (só brincando)
Eu não eliminaria o recurso porque é melhor escrever métodos curtos. É um pouco como dizer que você não deve usar threads porque são difíceis. Dê-me a faca e deixe-me ser responsável por não me cortar.
Pessoalmente, eu queria outra palavra-chave do tipo "var" como "inv" (invariente) ou "rvar" para evitar confusão. Tenho estudado F # recentemente e acho a coisa imutável atraente.
Nunca soube que Java tinha isso.
Gostaria de variáveis locais somente leitura da mesma maneira que gosto de variáveis locais const . Mas tem menos prioridade do que outros tópicos.
Talvez sua prioridade seja a mesma razão para que os designers de C # (ainda!) Não implementem esse recurso. Mas deve ser fácil (e compatível com versões anteriores) suportar variáveis locais somente leitura em versões futuras.
Somente leitura significa que o único lugar em que a variável de instância pode ser definida é no construtor. Ao declarar uma variável localmente, ela não tem uma instância (está apenas no escopo) e não pode ser tocada pelo construtor.
Eu sei, isso não responde o porquê da sua pergunta. De qualquer forma, aqueles que estão lendo esta pergunta podem apreciar o código abaixo.
Se você está realmente preocupado em dar um tiro no próprio pé ao substituir uma variável local que deve ser definida apenas uma vez, e não quer torná-la uma variável mais acessível globalmente, você poderia fazer algo assim.
public class ReadOnly<T>
{
public T Value { get; private set; }
public ReadOnly(T pValue)
{
Value = pValue;
}
public static bool operator ==(ReadOnly<T> pReadOnlyT, T pT)
{
if (object.ReferenceEquals(pReadOnlyT, null))
{
return object.ReferenceEquals(pT, null);
}
return (pReadOnlyT.Value.Equals(pT));
}
public static bool operator !=(ReadOnly<T> pReadOnlyT, T pT)
{
return !(pReadOnlyT == pT);
}
}
Exemplo de uso:
var rInt = new ReadOnly<int>(5);
if (rInt == 5)
{
//Int is 5 indeed
}
var copyValueOfInt = rInt.Value;
//rInt.Value = 6; //Doesn't compile, setter is private
Talvez não menos código, rvar rInt = 5mas funciona.
Você pode declarar variáveis locais somente leitura em C #, se estiver usando o compilador interativo C # csi:
>"C:\Program Files (x86)\MSBuild\14.0\Bin\csi.exe"
Microsoft (R) Visual C# Interactive Compiler version 1.3.1.60616
Copyright (C) Microsoft Corporation. All rights reserved.
Type "#help" for more information.
> readonly var message = "hello";
> message = "goodbye";
(1,1): error CS0191: A readonly field cannot be assigned to (except in a constructor or a variable initializer)
Você também pode declarar variáveis locais somente leitura no .csxformato de script.
messagenão é uma variável aqui, ela é compilada em um campo. Isso não é picuinhas porque a distinção existe claramente no C # interativo também: int x; Console.WriteLine(x)é C # interativo legal (porque xé um campo e inicializado implicitamente), mas void foo() { int x; Console.WriteLine(x); }não é (porque xé uma variável e usada antes de ser atribuída). Além disso, Expression<Func<int>> y = x; ((MemberExpression) y.Body).Member.MemberTyperevelará que xé realmente um campo e não uma variável local.
c # já tem um var somente leitura, embora em uma sintaxe um pouco diferente:
Considere as seguintes linhas:
var mutable = myImmutableCalculationMethod();
readonly var immutable = mutable; // not allowed in C# 8 and prior versions
return immutable;
Compare com:
var mutable = myImmutableCalculationMethod();
string immutable() => mutable; // allowed in C# 7
return immutable();
É certo que a primeira solução poderia ser menos código para escrever. Mas o segundo fragmento tornará o somente leitura explícito, ao fazer referência à variável.
readonly var im = new List<string>(); im.Add("read-only variable, mutable object!");.
usar const palavra-chave para tornar a variável somente leitura.
referência: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/const
public class SealedTest
{
static void Main()
{
const int c = 707;
Console.WriteLine("My local constant = {0}", c);
}
}
constonde a variável só pode ser atribuída durante sua inicialização - não no estilo csharp, constonde apenas expressões de tempo de compilação podem ser usadas. Por exemplo, você não pode fazer, const object c = new object();mas um readonlylocal permitiria que você fizesse isso.