Tipos nullables y el operador ternario: ¿por qué es`? 10: null` prohibido? [duplicar]


Esta pregunta ya tiene una respuesta aquí:

Acabo de encontrar un extraño error:

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 true, asigne 10 al Nullable intx. De lo contrario, asigne null al nullable int. Sin embargo, el compilador se queja:

Error 1 No se puede determinar el tipo de expresión condicional porque no hay conversión implícita entre int y <null>.

¿Me estoy volviendo loco?

Author: abatishchev, 2009-05-13

9 answers

El compilador primero intenta evaluar la expresión de la derecha:

GetBoolValue() ? 10 : null

El 10 es un int literal (no int?) y null es, bueno, null. No hay conversión implícita entre esos dos por lo tanto 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
 357
Author: LukeH,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-04-29 08:45:13

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 lanzar el null a un Nullable<int> le estamos diciendo al compilador explícitamente que el retorno type of this expression shall be a Nullable<int>. Podrías haber lanzado el 10 a int? también y haber tenido el mismo efecto.

 32
Author: Andrew Hare,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-05-13 14:06:06

Prueba esto:

int? result = condition ? 10 : default(int?);

 14
Author: Unknown,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-04-02 08:07:52

Por cierto, la implementación de Microsoft del compilador de C# en realidad obtiene el análisis de tipos del operador condicional mal de una manera muy sutil e interesante (para mí). Mi artículo sobre él es Tipo infortunios de inferencia, primera parte.

 13
Author: Eric Lippert,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-04-20 08:12:01

Prueba uno de estos:

int? x = GetBoolValue() ? (int?)10 : null;

int? x = GetBoolValue() ? 10 : (int?)null;
 4
Author: John Gietzen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-05-13 13:59:28

El problema es que el operador ternario infiere tipo basado en su primera asignación de parámetro...10 en este caso, que es un int, no un int nullable.

Usted podría tener mejor suerte con:

int? x = GetBoolValue() (int?)10 : null;
 4
Author: Justin Niessner,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-05-13 14:00:53
int? x = GetBoolValue() ? 10 : (int?)null;

La razón por la que ves esto es porque detrás de las escenas estás usando Nullable y necesitas decirle a C# que tu "null" es una instancia null de Nullable.

 3
Author: Martin Peck,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-05-13 13:57:23

Simplemente agrega un molde explícito.

int? x = GetBoolValue() ? 10 : (int?)null;

Es el operador ternario el que se confunde: el segundo argumento es un entero y también se prevé que el tercer argumento sea un entero, y null no encaja.

 3
Author: Daniel Brückner,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-05-13 14:00:03

Es porque el compilador determina el tipo del operador condicional por su segundo y tercer operando, no por lo que le asigna el resultado. No hay conversión directa entre un entero y una referencia nula que el compilador pueda usar para determinar el tipo.

 3
Author: Guffa,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-05-13 14:09:56