Parece estranho, especialmente para desenvolvedores C ++. Em C ++ costumávamos marcar um parâmetro como const
para ter certeza de que seu estado não será alterado no método. Existem também outros motivos específicos do C ++, como passar const ref
para passar por ref e ter certeza de que o estado não será alterado. Mas por que não podemos marcar como parâmetros de método const em C #?
Por que não posso declarar meu método como o seguinte?
....
static void TestMethod1(const MyClass val)
{}
....
static void TestMethod2(const int val)
{}
....
c#
language-agnostic
language-design
Incógnito
fonte
fonte
Respostas:
Além de outras boas respostas, acrescentarei outra razão para não colocar constância do estilo C no C #. Você disse:
Se const realmente fizesse isso, seria ótimo. Const não faz isso. O const é uma mentira!
Const não oferece nenhuma garantia de que eu possa realmente usar. Suponha que você tenha um método que usa uma coisa const. Existem dois autores de código: a pessoa que escreve o chamador e a pessoa que escreve o receptor . O autor do chamado fez com que o método assumisse uma const. O que os dois autores podem assumir é invariável em relação ao objeto?
Nada. O callee está livre para rejeitar const e transformar o objeto, portanto, o chamador não tem garantia de que chamar um método que usa const realmente não o fará sofrer mutação. Da mesma forma, o receptor não pode assumir que o conteúdo do objeto não mudará durante a ação do receptor; o callee pode chamar algum método mutante em um alias não const do objeto const, e agora o chamado objeto const mudou .
Const de estilo C não fornece garantia de que o objeto não será alterado e, portanto, está quebrado. Agora, C já tem um sistema de tipo fraco no qual você pode fazer uma reinterpretação de um duplo em um int se realmente quiser, então não deve ser uma surpresa que ele tenha um sistema de tipo fraco com respeito a const também. Mas C # foi projetado para ter um bom sistema de tipos, um sistema de tipos onde, quando você diz "esta variável contém uma string", a variável realmente contém uma referência a uma string (ou nula). Não queremos absolutamente colocar um modificador "const" no estilo C no sistema de tipos porque não queremos que o sistema de tipos seja uma mentira . Queremos que o sistema de tipos seja forte para que você possa raciocinar corretamente sobre o seu código.
Const em C é uma diretriz ; basicamente significa "você pode confiar em mim para não tentar transformar essa coisa". Isso não deveria estar no sistema de tipos ; as coisas no sistema de tipos devem ser um fato sobre o objeto sobre o qual você pode raciocinar, não uma diretriz para seu uso.
Agora, não me entenda mal; só porque const em C está profundamente quebrado não significa que todo o conceito seja inútil. O que eu adoraria ver é alguma forma realmente correta e útil de anotação "const" em C #, uma anotação que humanos e compiladores podem usar para ajudá-los a entender o código, e que o tempo de execução pode usar para fazer coisas como paralelização automática e outras otimizações avançadas.
Por exemplo, imagine se você pudesse "desenhar uma caixa" em torno de um pedaço de código e dizer " Garanto que esse pedaço de código não executa mutações em nenhum campo desta classe" de uma forma que pudesse ser verificada pelo compilador. Ou desenhe uma caixa que diga "este método puro altera o estado interno do objeto, mas não de qualquer maneira que seja observável fora da caixa". Esse objeto não poderia ser multithread automaticamente com segurança, mas poderia ser memoized automaticamente . Existem todos os tipos de anotações interessantes que poderíamos colocar no código que permitiriam otimizações ricas e um entendimento mais profundo. Podemos fazer muito melhor do que a fraca anotação const do estilo C.
No entanto, enfatizo que isso é apenas especulação . Não temos planos firmes de colocar esse tipo de recurso em qualquer versão futura hipotética do C #, se é que existe uma, que não anunciamos de uma forma ou de outra. É algo que eu adoraria ver e algo que a próxima ênfase na computação de vários núcleos pode exigir, mas nada disso deve ser interpretado de forma alguma como uma previsão ou uma garantia de qualquer recurso particular ou direção futura para C #.
Agora, se o que você deseja é apenas uma anotação na variável local que é um parâmetro que diz "o valor deste parâmetro não muda ao longo do método", então, claro, isso seria feito facilmente. Poderíamos suportar locais e parâmetros "somente leitura" que seriam inicializados uma vez e um erro em tempo de compilação para alterar o método. A variável declarada pela instrução "using" já é um local; poderíamos adicionar uma anotação opcional a todos os locais e parâmetros para fazê-los agir como variáveis "usando". Nunca foi um recurso de prioridade muito alta, então nunca foi implementado.
fonte
0xDEADBEEF
. Mas ambos seriam uma programação muito ruim , e detectados cedo e de forma pungente por qualquer compilador moderno. No futuro, ao escrever as respostas, por favor, não confunda o que é tecnicamente possível usando backdoors de uma linguagem com o que é viável no código do mundo real. Informações distorcidas como essa confundem leitores menos experientes e degradam a qualidade das informações no SO.Um dos motivos pelos quais não há correção const em C # é porque ele não existe no nível de tempo de execução. Lembre-se de que C # 1.0 não tinha nenhum recurso, a menos que fizesse parte do tempo de execução.
E várias razões pelas quais o CLR não tem uma noção de correção const são, por exemplo:
A correção Const é basicamente um recurso de linguagem presente apenas em C ++. Portanto, tudo se resume à mesma argumentação sobre por que o CLR não exige exceções verificadas (que é um recurso exclusivo da linguagem Java).
Além disso, não acho que você pode introduzir um recurso de sistema de tipo fundamental em um ambiente gerenciado sem quebrar a compatibilidade com versões anteriores. Portanto, não conte com a correção const entrando no mundo do C #.
fonte
ref
parâmetro (especialmente, no caso de métodos / propriedades de estruturathis
). Se um método declara especificamente que não gravará em umref
parâmetro, o compilador deve permitir que valores somente leitura sejam passados. Por outro lado, se um método afirma que gravaráthis
, o compilador não deve permitir que tal método seja chamado em valores somente leitura.Eu acredito que há duas razões pelas quais C # não é constante.
O primeiro é a compreensibilidade . Poucos programadores C ++ entendem correção const. O exemplo simples de
const int arg
é bonito, mas eu também vichar * const * const arg
- um ponteiro constante para ponteiros constantes para caracteres não constantes. A correção constante de ponteiros para funções é um nível totalmente novo de ofuscação.A segunda é porque os argumentos da classe são referências passadas por valor. Isso significa que já existem dois níveis de constância para lidar, sem uma sintaxe obviamente clara . Um ponto de tropeço semelhante são as coleções (e coleções de coleções, etc.).
A correção constante é uma parte importante do sistema de tipos C ++. Ele poderia - em teoria - ser adicionado ao C # como algo que só é verificado em tempo de compilação (não precisa ser adicionado ao CLR e não afetaria o BCL a menos que a noção de métodos de membro const fossem incluídos) .
No entanto, acredito que isso seja improvável: o segundo motivo (sintaxe) seria bastante difícil de resolver, o que tornaria o primeiro motivo (compreensibilidade) ainda mais problemático.
fonte
modopt
emodreq
no nível de metadados para armazenar essa informação (como C + / CLI já faz - vejaSystem.Runtime.CompilerServices.IsConst
); e isso poderia ser estendido trivialmente aos métodos const também.const
significa "constante de tempo de compilação" em C #, não "somente leitura, mas possivelmente mutável por outro código" como em C ++. Um análogo aproximado de C ++const
em C # éreadonly
, mas só se aplica a campos. Além disso, não há nenhuma noção semelhante à do C ++ de correção const em C #.O raciocínio é difícil de dizer com certeza, porque há muitos motivos potenciais, mas meu palpite seria o desejo de manter a linguagem simples em primeiro lugar e as vantagens incertas de implementar isso em segundo lugar.
fonte
Isso é possível desde C # 7.2 (dezembro de 2017 com Visual Studio 2017 15.5).
Apenas para estruturas e tipos básicos ! , não para membros de classes.
Você deve usar
in
para enviar o argumento como uma entrada por referência. Vejo:Consulte: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/in-parameter-modifier
Para seu exemplo:
fonte