Compartilhar via


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

  1. não há nenhum tipo comum para e1 e e2, ou
  2. para o qual existe um tipo comum, mas uma das expressões e1 ou e2 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ão E para um tipo T1e uma conversão implícita C2 que converte de uma expressão E para um tipo T2, C1 é uma conversão melhor do que C2 se E não corresponder exatamente a T2 e pelo menos uma das seguintes condições for atendida:

  • E corresponde exatamente T1 (§12.6.4.5)
  • T1 é um destino de conversão melhor do que T2 (§12.6.4.7)

até

Melhor conversão da expressão

Dadas uma conversão implícita C1 que converte de uma expressão E para um tipo T1e uma conversão implícita C2 que converte de uma expressão E para um tipo T2, C1 é uma conversão melhor do que C2 se E não corresponder exatamente a T2 e pelo menos uma das seguintes condições for atendida:

  • E corresponde exatamente T1 (§12.6.4.5)
  • C1 não é uma conversão de expressão condicional e C2 é uma conversão de expressão condicional.
  • T1 é um melhor destino de conversão do que T2 (§12.6.4.7) , e ou C1 e C2 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, onde T é um tipo e E é uma unary_expression, realiza uma conversão explícita (§10.3) do valor de E para o tipo T.

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