Tipos que aceptan valores NULL y el operador ternario:¿Por qué es `?10:nulo` prohibido?[duplicar]
-
21-08-2019 - |
Pregunta
Esta pregunta ya tiene respuesta aquí:
- ¿Asignación de operador condicional con tipos Nullable<valor>? 5 respuestas
- ¿Por qué no se compila este código C#? 4 respuestas
Me acabo de encontrar con un error extraño:
private bool GetBoolValue()
{
//Do some logic and return true or false
}
Luego, en otro método, algo como esto:
int? x = GetBoolValue() ? 10 : null;
Simple, si el método devuelve verdadero, asigna 10 a Nullableint
X.De lo contrario, asigne nulo al anulable En t.Sin embargo, el compilador se queja:
Error 1 No se puede determinar el tipo de expresión condicional porque no hay una conversión implícita entre
int
y<null>
.
¿Me estoy volviendo loco?
Solución
El compilador primero intenta evaluar la expresión de la derecha:
GetBoolValue() ? 10 : null
El 10
es un int
literal (no int?
) y null
esta bien, null
.No hay ninguna conversión implícita entre esos dos, de ahí el mensaje de error.
Si cambia la expresión de la derecha a una de las siguientes, se compila porque hay una conversión implícita entre int?
y null
(#1) y entre int
y int?
(#2, #3).
GetBoolValue() ? (int?)10 : null // #1
GetBoolValue() ? 10 : (int?)null // #2
GetBoolValue() ? 10 : default(int?) // #3
Otros consejos
Prueba esto:
int? x = GetBoolValue() ? 10 : (int?)null;
Básicamente lo que está sucediendo es que el operador condicional es incapaz de determinar el "tipo de retorno" de la expresión. Desde el compilador decide implictitly que 10
es un int
entonces decide que el tipo de retorno de esta expresión será un null
también. Desde un Nullable<int>
no puede ser int?
(el tercer operando del operador condicional) se queja.
Por la fundición <=> a un <=> le estamos diciendo al compilador explícitamente que el tipo de retorno de esta expresión será un <=>. Que podría haber la misma facilidad fundido el <=> a <=> así y tenía el mismo efecto.
Prueba esto:
int? result = condition ? 10 : default(int?);
Por cierto, la implementación de Microsoft del compilador de C # en realidad recibe el análisis del tipo de operador condicional equivocada de una manera muy sutil e interesante (para mí). Mi artículo en él es problemas de inferencia de tipos, primera parte .
Pruebe uno de los siguientes:
int? x = GetBoolValue() ? (int?)10 : null;
int? x = GetBoolValue() ? 10 : (int?)null;
El problema es que el operador ternario está infiriendo tipo basado en su primera parametrización 10 ... en este caso, que es un int, no un int anulable.
Es posible que tenga mejor suerte con:
int? x = GetBoolValue() (int?)10 : null;
int? x = GetBoolValue() ? 10 : (int?)null;
La razón por la que ves esto es porque detrás de las escenas que está utilizando anulable y hay que decir que su C # "nulo" es una instancia nula de anulable.
Sólo tiene que añadir un reparto explict.
int? x = GetBoolValue() ? 10 : (int?)null;
Es el operador ternario que se confunde -. El segundo argumento es un número entero y también lo es el tercer argumento exspected a ser un número entero, también, y nulo no encaja
Es porque el compilador determina el tipo de operador condicional por su segundo y tercer operando, no por lo que se asigna el resultado a. No hay reparto directo entre un número entero y una referencia nula de que el compilador puede utilizar para determinar el tipo.