Sem implícito int -> conversão curta na declaração ternária
-
16-09-2019 - |
Pergunta
short s;
s = (EitherTrueOrFalse()) ? 0 : 1;
Isso falha com:
Erro CS0266: Não é possível converter implicitamente o tipo 'int' para 'curto'. Existe uma conversão explícita (você está perdendo um elenco?)
Alguém pode explicar por que é assim? A única coisa que consigo pensar é que o compilador não olha para o segundo valor e não sabe o intervalo entre os dois, no caso em que escrevi algo como
short s;
s = (EitherTrueOrFalse()) ? 0 : 65000;
Correto? A única correção é com um elenco feio?
Além disso, parece que C# não possui um sufixo do tipo para o tipo curto. Essa é uma supervisão bastante grave da IMO. Caso contrário, isso teria sido uma solução ...
Solução
O compilador tem uma conversão implícita de um constante Expressão para vários tipos primitivos (desde que o valor esteja dentro do intervalo apropriado), mas aqui a expressão não é constante - é apenas uma expressão int. É praticamente o mesmo que:
short s;
s = CallSomeMethodReturningInt32();
No que diz respeito ao compilador.
Existem duas opções - você pode lançar toda a expressão ou lançar cada uma das duas últimas operando:
short s = (EitherTrueOrFalse()) ? (short) 0 : (short) 1;
Para fazer o tipo de expressão geral short
. Nesse caso em particular, é uma pena que não haja um sufixo literal numérico para declarar explicitamente um short
literal. Aparentemente, os designers de idiomas consideraram isso, mas sentiram que era uma situação relativamente rara. (Acho que provavelmente concordo.)
A parte sobre conversões constantes implícitas é da seção C# 3.0 Spec Seção 6.1.8:
6.1.8 Conversões implícitas de expressão constante
Uma conversão de expressão constante implícita permite as seguintes conversões:
- UMA expressão constante (§7.18) do tipo
int
pode ser convertido para o tipo sbyte,byte
,short
,ushort
,uint
, ouulong
, desde que o valor do expressão constante está dentro do intervalo do tipo de destino.- UMA expressão constante do tipo
long
pode ser convertido para tipoulong
, desde que o valor do expressão constantenão é negativo.
Outras dicas
Porque o O elenco é feito pelo compilador, não em tempo de execução, eu não chamaria de elenco feio, eu chamaria de sintaxe complicada:
s = (EitherTrueOrFalse()) ? (short)0 : (short)1;
Quero dizer, é assim que está escrito em C#, mesmo que pareça feio.
Veja isso Artigo do blog. Ver Resposta de Marc Granell nessa questão.
Eu acho que isso tem o mesmo motivo que não vai compilar:
short s1 = GetShort1();
short s2 = GetShort2();
short s3 = s1 + s2;
Ou seja, sempre que o curto é usado para alguma coisa, ele é promovido ao Int.