¿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 x
y y
tienen un tipo y se cumplen ciertas buenas condiciones , solo una de x
y y
tiene 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
x
yy
tiene un tipo, y ambosx
yy
son 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í x
hay un int
literal, y y
es el null
que no tiene un tipo y null
no es implícitamente convertible a un int
1 . 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 x
y y
tiene 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?)5
y null
ambos 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
x
tiene tipoX
yy
tiene tipo,Y
entonces
Si existe una conversión implícita (§6.1) de
X
aY
, pero no deY
aX
, entoncesY
es el tipo de expresión condicional.Si existe una conversión implícita (§6.1) de
Y
aX
, pero no deX
aY
, entoncesX
es 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í x
es de tipo int
y y
es de tipo int?
. No hay conversión implícita de int?
a int
, pero hay una conversión implícita de int
a, 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
.
DateTime
enviar 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 null
no 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# 9
este 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;