Por que isso não compila?
int? number = true ? 5 : null;
O tipo de expressão condicional não pode ser determinado porque não há conversão implícita entre 'int' e <null>
Por que isso não compila?
int? number = true ? 5 : null;
O tipo de expressão condicional não pode ser determinado porque não há conversão implícita entre 'int' e <null>
Respostas:
A especificação (§7.14) diz que para a expressão condicional b ? x : y, há três possibilidades, tanto xe yambos têm um tipo e certas condições boas são atendidas, apenas um xe ytem um tipo e certa condições boas são cumpridos, ou um erro de tempo de compilação ocorre. Aqui, "certas boas condições" significa que certas conversões são possíveis, as quais entraremos em detalhes abaixo.
Agora, passemos à parte pertinente da especificação:
Se apenas um de
xeytiver um tipo, e ambosxeyforem implicitamente conversíveis nesse tipo, esse é o tipo da expressão condicional.
A questão aqui é que, em
int? number = true ? 5 : null;
apenas um dos resultados condicionais tem um tipo. Aqui xestá um intliteral, e yé o nullque não tem um tipo e nullnão é implicitamente conversível em um int1 . Portanto, "certas boas condições" não são atendidas e ocorre um erro em tempo de compilação.
Não são duas maneiras de contornar isso:
int? number = true ? (int?)5 : null;
Aqui ainda estamos no caso em que apenas um de xe ytem um tipo. Observe que null ainda não possui um tipo, o compilador não terá nenhum problema com isso, porque (int?)5enull são ambos implicitamente conversível para int?(§6.1.4 e §6.1.5).
A outra maneira é obviamente:
int? number = true ? 5 : (int?)null;
mas agora precisamos ler uma cláusula diferente na especificação para entender por que isso está correto:
Se
xtem tipoXeytem tipo,Yentão
Se existir uma conversão implícita (§6.1) de
XparaY, mas não deYparaX, entãoYé o tipo da expressão condicional.Se existir uma conversão implícita (§6.1) de
YparaX, mas não deXparaY, entãoXé o tipo da expressão condicional.Caso contrário, nenhum tipo de expressão poderá ser determinado e ocorrerá um erro em tempo de compilação.
Aqui xé do tipo inte yé do tipo int?. Não há conversão implícita de int?para int, mas há uma conversão implícita de intparaint? portanto o tipo da expressão é int?.
1 : Observe ainda que o tipo do lado esquerdo é ignorado na determinação do tipo da expressão condicional, uma fonte comum de confusão aqui.
new int?()no lugar de (int?)null.
DateTime, quando de facto necessário(DateTime?)
null não tem nenhum tipo identificável - ele só precisa de um pouco de estímulo para torná-lo feliz:
int? number = true ? 5 : (int?)null;
int? number = true ? 5 : null as int?;
int? number = true ? 5 : (int?)null;e os int? number = true ? (int?)5 : null;dois compilam !! Scratch, scratch
Como outros já mencionaram, o 5 é um inte nullnão pode ser implicitamente convertido em int.
Aqui estão outras maneiras de solucionar o problema:
int? num = true ? 5 : default(int?);
int? num = true ? 5 : new int?();
int? num = true ? 5 : null as int?;
int? num = true ? 5 : (int?)null;
int? num = true ? (int?)5 : null;
int? num = true ? 5 as int? : null;
int? num = true ? new int?(5) : null;
Além disso, em qualquer lugar que você ver int?, você também pode usar Nullable<int>.
No C# 9presente é agora permitido blogue
Alvo digitado ?? e?
Às vezes condicional ?? e?: as expressões não têm um tipo compartilhado óbvio entre os ramos. Esses casos falham hoje, mas o C # 9.0 os permitirá se houver um tipo de destino para o qual os dois ramos se convertam:
Person person = student ?? customer; // Shared base type
int? result = b ? 0 : null; // nullable value type
Ou seu exemplo:
// Allowed in C# 9.
int? number = true ? 5 : null;