Expressão Condicional com Tipo de Destino
Observação
Este artigo é uma especificação de recurso. A especificação serve como o documento de design para o recurso. Ela inclui alterações de especificação propostas, juntamente com as informações necessárias durante o design e o desenvolvimento do recurso. Esses artigos são publicados até que as alterações de especificação propostas sejam finalizadas e incorporadas na especificação ECMA atual.
Pode haver algumas divergências entre a especificação do recurso e a implementação concluída. Essas diferenças são capturadas nas notas pertinentes da reunião de design de idioma (LDM).
Você pode saber mais sobre o processo de adoção de speclets de recursos no padrão de linguagem C# no artigo sobre as especificações de .
Problema do especialista: https://github.com/dotnet/csharplang/issues/2460
Conversão de expressão condicional
Para uma expressão condicional c ? e1 : e2
, quando
- não há nenhum tipo comum para
e1
ee2
, ou - para o qual existe um tipo comum, mas uma das expressões
e1
oue2
não tem conversão implícita para esse tipo
definimos uma nova conversão de expressão condicional implícita que permite uma conversão implícita da expressão condicional para qualquer tipo T
para o qual há uma conversão de expressão de e1
para T
e também de e2
para T
. Será um erro se uma expressão condicional não tiver um tipo comum entre e1
e e2
nem estiver sujeita a uma conversão de expressão condicional .
Melhor Conversão da Expressão
Nós mudamos
Melhor conversão da expressão
Dadas uma conversão implícita
C1
que converte de uma expressãoE
para um tipoT1
e uma conversão implícitaC2
que converte de uma expressãoE
para um tipoT2
,C1
é uma conversão melhor do queC2
seE
não corresponder exatamente aT2
e pelo menos uma das seguintes condições for atendida:
até
Melhor conversão da expressão
Dadas uma conversão implícita
C1
que converte de uma expressãoE
para um tipoT1
e uma conversão implícitaC2
que converte de uma expressãoE
para um tipoT2
,C1
é uma conversão melhor do queC2
seE
não corresponder exatamente aT2
e pelo menos uma das seguintes condições for atendida:
E
corresponde exatamenteT1
(§12.6.4.5)C1
não é uma conversão de expressão condicional eC2
é uma conversão de expressão condicional.T1
é um melhor destino de conversão do queT2
(§12.6.4.7) , e ouC1
eC2
são ambos conversões de expressão condicional , ou nenhum dos dois é uma conversão de expressão condicional .
Expressão de Conversão
A especificação atual da linguagem C# diz
Uma cast_expression do formulário
(T)E
, ondeT
é um tipo eE
é uma unary_expression, realiza uma conversão explícita (§10.3) do valor deE
para o tipoT
.
Na presença da conversão de expressão condicional, pode haver mais de uma conversão possível de E
para T
. Com a adição de conversão de expressão condicional, preferimos qualquer outra conversão em uma conversão de expressão condicional e usamos a conversão de expressão condicional apenas como último recurso.
Observações sobre design
O motivo da alteração para Melhor conversão da expressão é lidar com um caso como este:
M(b ? 1 : 2);
void M(short);
void M(long);
Essa abordagem traz duas pequenas desvantagens. Primeiramente, não é exatamente o mesmo que a expressão switch:
M(b ? 1 : 2); // calls M(long)
M(b switch { true => 1, false => 2 }); // calls M(short)
Essa ainda é uma alteração significativa, mas seu escopo é menos provável que afete programas reais:
M(b ? 1 : 2, 1); // calls M(long, long) without this feature; ambiguous with this feature.
M(short, short);
M(long, long);
Isso se torna ambíguo porque a conversão em long
é melhor para o primeiro argumento (porque ele não usa a conversão de expressão condicional ), mas a conversão para short
é melhor para o segundo argumento (porque short
é um destino de conversão melhor do que long
). Essa mudança parece menos grave porque não modifica silenciosamente o comportamento de um programa existente.
O motivo das anotações na expressão de conversão é lidar com um caso como este:
_ = (short)(b ? 1 : 2);
Atualmente, este programa usa a conversão explícita de int
para short
e queremos preservar o significado da linguagem atual deste programa. A alteração seria inobservável no runtime, mas seria observável com o seguinte programa:
_ = (A)(b ? c : d);
em que c
é do tipo C
, d
é do tipo D
e há uma conversão implícita definida pelo usuário de C
para D
, e uma conversão implícita definida pelo usuário de D
para A
e uma conversão implícita definida pelo usuário de C
para A
. Se esse código for compilado antes do C# 9.0, quando b
for verdadeiro, converteremos de c
para D
para A
. Se usarmos a conversão de expressão condicional, quando b
for verdadeira, converteremos de c
para A
diretamente, o que executará uma sequência diferente de código de usuário. Portanto, tratamos a conversão de expressão condicional como último recurso em uma conversão, para preservar o comportamento existente.
C# feature specifications