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 nullaú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í.
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:
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:newint?();int? num =true?5:nullasint?;int? num =true?5:(int?)null;int? num =true?(int?)5:null;int? num =true?5asint?:null;int? num =true?newint?(5):null;
Además, en cualquier lugar que vea int?, también puede usar Nullable<int>.
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 typeint? result = b ?0:null;// nullable value type
Respuestas:
La especificación (§7.14) dice que para la expresión condicional
b ? x : y
, hay tres posibilidades, ambasx
yy
tienen un tipo y se cumplen ciertas buenas condiciones , solo una dex
yy
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:
El problema aquí es que en
solo uno de los resultados condicionales tiene un tipo. Aquí
x
hay unint
literal, yy
es elnull
que no tiene un tipo ynull
no es implícitamente convertible a unint
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:
Aquí todavía estamos en el caso donde solo uno de
x
yy
tiene un tipo. Tenga en cuenta quenull
aún no tiene un tipo, sin embargo, el compilador no tendrá ningún problema con esto porque(int?)5
ynull
ambos son implícitamente convertibles aint?
(§6.1.4 y §6.1.5).La otra forma es obviamente:
pero ahora tenemos que leer una cláusula diferente en la especificación para entender por qué esto está bien:
Aquí
x
es de tipoint
yy
es de tipoint?
. No hay conversión implícita deint?
aint
, pero hay una conversión implícita deint
a,int?
por lo que el tipo de expresión esint?
.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í.
fuente
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:fuente
int? number = true ? 5 : null as int?;
null
no tenga un tipo identificable. El problema es que no hay conversión implícita denull
aint
. Detalles aquí .int? number = true ? 5 : (int?)null;
yint? number = true ? (int?)5 : null;
ambos compilan !! Scratch, scratchComo otros han mencionado, el 5 es un
int
, ynull
no se puede convertir implícitamente aint
.Aquí hay otras formas de solucionar el problema:
Además, en cualquier lugar que vea
int?
, también puede usarNullable<int>
.fuente
En
C# 9
este blog ahora está permitidoO tu ejemplo:
fuente