El tipo de expresión condicional no se puede determinar porque no hay conversión implícita entre 'int' y <null>

Respuestas:

339

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 xy ytiene un tipo, y ambos xy yson 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 tipo Xy ytiene tipo, Yentonces

  • Si existe una conversión implícita (§6.1) de Xa Y, pero no de Ya X, entonces Yes el tipo de expresión condicional.

  • Si existe una conversión implícita (§6.1) de Ya X, pero no de Xa Y, entonces Xes 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í.

jason
fuente
44
Buena cita de la especificación para ilustrar por qué sucede esto: ¡+1!
JerKimball
77
Otra opción está new int?()en lugar de (int?)null.
Guvante
1
Este también es el caso si tiene un tipo de campo de base de datos anulable, por ejemplo, un DateTime anulable e intenta DateTimeenviar datos , cuando sea necesario(DateTime?)
Mike Upjohn
73

null no tiene ningún tipo identificable, solo necesita un poco de insistencia para hacerlo feliz:

int? number = true ? 5 : (int?)null;
Marc Gravell
fuente
2
O puede hacerloint? number = true ? 5 : null as int?;
Brad M
Buena respuesta clavando el punto. Buena lectura relacionada: ericlippert.com/2013/05/30/what-the-meaning-of-is-is
Benjamin Gruenbaum
El problema no es que nullno tenga un tipo identificable. El problema es que no hay conversión implícita de nulla int. Detalles aquí .
Jason
lo interesante es que int? number = true ? 5 : (int?)null;y int? number = true ? (int?)5 : null;ambos compilan !! Scratch, scratch
davidhq
2
Cubro exactamente por qué sucede esto en mi respuesta .
Jason
4

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

Andrés
fuente
1

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;
WBuck
fuente