c# - valor - tipo de dato null
Los tipos anulables y el operador ternario: ¿por qué es `? 10: null` prohibido? (9)
Esta pregunta ya tiene una respuesta aquí:
- ¿Asignación de operador condicional con tipos <valor> anulables? 5 respuestas
- ¿Por qué no compila este código C #? 4 respuestas
Acabo de encontrar 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, asigne 10 al Nullable int
x. De lo contrario, asigne nulo al int. Sin embargo, el compilador se queja:
Error 1 El tipo de expresión condicional no se puede determinar porque no hay una conversión implícita entre
int
y<null>
.
¿Me estoy volviendo loco?
El compilador primero intenta evaluar la expresión de la mano derecha:
GetBoolValue() ? 10 : null
El 10
es un int
literal (no int?
) Y null
es, bueno, null
. No hay una conversión implícita entre esos dos, de ahí el mensaje de error.
Si cambia la expresión de la mano derecha a una de las siguientes, se compila porque hay una conversión implícita entre int?
y null
(# 1) y entre int
e int?
(# 2, # 3).
GetBoolValue() ? (int?)10 : null // #1
GetBoolValue() ? 10 : (int?)null // #2
GetBoolValue() ? 10 : default(int?) // #3
El problema es que el operador ternario está inferiendo el tipo basado en su primera asignación de parámetros ... 10 en este caso, que es un int, no un int.
Podrías tener mejor suerte con:
int? x = GetBoolValue() (int?)10 : null;
Es porque el compilador determina el tipo de operador condicional por su segundo y tercer operando, no por lo que asigna el resultado. No hay conversión directa entre un entero y una referencia nula que el compilador puede usar para determinar el tipo.
Incidentalmente, la implementación de Microsoft del compilador de C # realmente hace que el análisis de tipo del operador condicional sea incorrecto de una manera muy sutil e interesante (para mí). Mi artículo sobre esto es Tipo inferencia de problemas, primera parte .
Prueba esto:
int? result = condition ? 10 : default(int?);
Prueba esto:
int? x = GetBoolValue() ? 10 : (int?)null;
Básicamente, lo que está sucediendo es que el operador condicional no puede determinar el "tipo de retorno" de la expresión. Dado que el compilador decide implícitamente que 10
es un int
, entonces decide que el tipo de retorno de esta expresión también será un int
. Dado que un int
no puede ser null
(el tercer operando del operador condicional) se queja.
Al Nullable<int>
el null
en un Nullable<int>
le estamos diciendo al compilador explícitamente que el tipo de retorno de esta expresión será un Nullable<int>
. ¿Podrías haber lanzado tan fácilmente el 10
a int?
También y tuvo el mismo efecto.
Pruebe uno de estos:
int? x = GetBoolValue() ? (int?)10 : null;
int? x = GetBoolValue() ? 10 : (int?)null;
Sólo tiene que añadir un elenco explícito.
int? x = GetBoolValue() ? 10 : (int?)null;
Es el operador ternario el que se confunde: el segundo argumento es un número entero y también se espera que el tercer argumento sea un número entero, y el valor nulo no se ajusta.
int? x = GetBoolValue() ? 10 : (int?)null;
La razón por la que ve esto es porque detrás de las escenas está usando Nullable y necesita decirle a C # que su "nulo" es una instancia nula de Nullable.