Atribuição de coalescência nula
Observação
Este artigo é uma especificação de recurso. A especificação serve como o documento de design para o recurso. Ele inclui mudanças de especificação propostas, juntamente com as informações necessárias durante o design e desenvolvimento do recurso. Estes artigos são publicados até que as alterações de especificações propostas sejam finalizadas e incorporadas na especificação ECMA atual.
Pode haver algumas discrepâncias entre a especificação do recurso e a implementação concluída. Essas diferenças são capturadas nas notas pertinentes da Language Design Meeting (LDM).
Você pode saber mais sobre o processo de adoção de especificações de recursos no padrão de linguagem C# no artigo sobre as especificações .
Questão campeã: https://github.com/dotnet/csharplang/issues/34
Resumo
Simplifica um padrão de codificação comum em que uma variável recebe um valor se for nulo.
Como parte desta proposta, também afrouxaremos os requisitos de tipo em ??
para permitir que uma expressão cujo tipo é um parâmetro de tipo sem restrições seja usada no lado esquerdo.
Motivação
É comum ver código do formulário
if (variable == null)
{
variable = expression;
}
Esta proposta adiciona um operador binário não sobrecarregável à linguagem que executa esta função.
Houve pelo menos oito solicitações separadas da comunidade para esse recurso.
Design detalhado
Adicionamos uma nova forma de operador de atribuição
assignment_operator
: '??='
;
Que segue as regras semânticas existentes para operadores de atribuição compostos (§12.21.4), exceto que eliminemos a atribuição se o lado esquerdo não for nulo. As regras para este recurso são as seguintes.
Dado a ??= b
, onde A
é o tipo de a
, B
é o tipo de b
e A0
é o tipo subjacente de A
se A
é um tipo de valor anulável:
- Se
A
não existir ou for um tipo de valor não anulável, ocorrerá um erro em tempo de compilação. - Se
B
não for implicitamente convertível emA
ouA0
(seA0
existir), ocorrerá um erro em tempo de compilação. - Se
A0
existe eB
é implicitamente conversível emA0
, eB
não é dinâmico, então o tipo dea ??= b
éA0
.a ??= b
é avaliado durante o tempo de execução como:
Só quevar tmp = a.GetValueOrDefault(); if (!a.HasValue) { tmp = b; a = tmp; } tmp
a
só é avaliada uma vez. - Caso contrário, o tipo de
a ??= b
éA
.a ??= b
é avaliada em tempo de execução comoa ?? (a = b)
, exceto quea
é avaliada apenas uma vez.
Para a flexibilização dos requisitos de tipo de ??
, atualizamos a especificação, que afirma atualmente que, considerando a ?? b
, onde A
é o tipo de a
:
- Se A existir e não for um tipo anulável ou um tipo de referência, ocorrerá um erro em tempo de compilação.
Flexibilizamos este requisito para:
- Se A existir e for um tipo de valor não anulável, ocorrerá um erro em tempo de compilação.
Isso permite que o operador coalescing nulo trabalhe em parâmetros de tipo não restritos, pois o parâmetro de tipo não restrito T
existe, não é um tipo anulável e não é um tipo de referência.
Desvantagens
Como acontece com qualquer recurso de linguagem, devemos questionar se a complexidade adicional para a linguagem é compensada na clareza adicional oferecida ao corpo de programas C# que se beneficiariam do recurso.
Alternativas
O programador pode escrever (x = x ?? y)
, if (x == null) x = y;
ou x ?? (x = y)
à mão.
Questões por resolver
- [ ] Devemos também apoiar os operadores
&&=
e||=
?
Reuniões de design
Nenhuma.
C# feature specifications