Partilhar via


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 be A0 é o tipo subjacente de A se A é um tipo de valor anulável:

  1. Se A não existir ou for um tipo de valor não anulável, ocorrerá um erro em tempo de compilação.
  2. Se B não for implicitamente convertível em A ou A0 (se A0 existir), ocorrerá um erro em tempo de compilação.
  3. Se A0 existe e B é implicitamente conversível em A0, e B não é dinâmico, então o tipo de a ??= b é A0. a ??= b é avaliado durante o tempo de execução como:
    var tmp = a.GetValueOrDefault();
    if (!a.HasValue) { tmp = b; a = tmp; }
    tmp
    
    Só que a só é avaliada uma vez.
  4. Caso contrário, o tipo de a ??= b é A. a ??= b é avaliada em tempo de execução como a ?? (a = b), exceto que a é 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:

  1. 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:

  1. 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.