¿Por qué esto no compila?
int? number = true ? 5 : null;
El tipo de expresión condicional no se puede determinar porque no hay conversión implícita entre 'int' y <null>
¿Por qué esto no compila?
int? number = true ? 5 : null;
El tipo de expresión condicional no se puede determinar porque no hay conversión implícita entre 'int' y <null>
Respuestas:
La especificación (§7.14) dice que para la expresión condicional b ? x : y, hay tres posibilidades, ambas xy ytienen un tipo y se cumplen ciertas buenas condiciones , solo una de xy ytiene un tipo y se cumplen ciertas buenas condiciones , o un error en tiempo de compilación ocurre. Aquí, "ciertas buenas condiciones" significa que son posibles ciertas conversiones, que veremos en los detalles a continuación.
Ahora, pasemos a la parte pertinente de la especificación:
Si solo uno de
xyytiene un tipo, y ambosxyyson implícitamente convertibles a ese tipo, entonces ese es el tipo de la expresión condicional.
El problema aquí es que en
int? number = true ? 5 : null;
solo uno de los resultados condicionales tiene un tipo. Aquí xhay un intliteral, y yes el nullque no tiene un tipo y nullno es implícitamente convertible a un int1 . Por lo tanto, no se cumplen "ciertas buenas condiciones" y se produce un error en tiempo de compilación.
No son dos maneras de evitar esto:
int? number = true ? (int?)5 : null;
Aquí todavía estamos en el caso donde solo uno de xy ytiene un tipo. Tenga en cuenta que null aún no tiene un tipo, sin embargo, el compilador no tendrá ningún problema con esto porque (int?)5y nullambos son implícitamente convertibles a int?(§6.1.4 y §6.1.5).
La otra forma es obviamente:
int? number = true ? 5 : (int?)null;
pero ahora tenemos que leer una cláusula diferente en la especificación para entender por qué esto está bien:
Si
xtiene tipoXyytiene tipo,Yentonces
Si existe una conversión implícita (§6.1) de
XaY, pero no deYaX, entoncesYes el tipo de expresión condicional.Si existe una conversión implícita (§6.1) de
YaX, pero no deXaY, entoncesXes el tipo de expresión condicional.De lo contrario, no se puede determinar el tipo de expresión y se produce un error en tiempo de compilación.
Aquí xes de tipo inty yes de tipo int?. No hay conversión implícita de int?a int, pero hay una conversión implícita de inta, int?por lo que el tipo de expresión es int?.
1 : Observe además que el tipo del lado izquierdo se ignora al determinar el tipo de expresión condicional, una fuente común de confusión aquí.
new int?()en lugar de (int?)null.
DateTimeenviar datos , cuando sea necesario(DateTime?)
null no tiene ningún tipo identificable, solo necesita un poco de insistencia para hacerlo feliz:
int? number = true ? 5 : (int?)null;
int? number = true ? 5 : null as int?;
int? number = true ? 5 : (int?)null;y int? number = true ? (int?)5 : null;ambos compilan !! Scratch, scratch
Como otros han mencionado, el 5 es un int, y nullno se puede convertir implícitamente a int.
Aquí hay otras formas de solucionar el 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;
Además, en cualquier lugar que vea int?, también puede usar Nullable<int>.
En C# 9este blog ahora está permitido
Objetivo escrito? y?
A veces condicional? y?: las expresiones no tienen un tipo compartido obvio entre las ramas. Tales casos fallan hoy, pero C # 9.0 los permitirá si hay un tipo de destino al que ambas ramas se convierten:
Person person = student ?? customer; // Shared base type
int? result = b ? 0 : null; // nullable value type
O tu ejemplo:
// Allowed in C# 9.
int? number = true ? 5 : null;