¿El "?."operator hacer algo más aparte de la comprobación de null?


Como puede que sepas, DateTime? no tiene un ToString parametrizado (con el propósito de formatear la salida), y hacer algo como

DateTime? dt = DateTime.Now;
string x;
if(dt != null)
    x = dt.ToString("dd/MM/yyyy");

Lanzará

Sin sobrecarga para el método 'toString' toma 1 argumentos

Pero, desde C # 6.0 y el operador Elvis (?.), el código anterior se puede reemplazar por

x = dt?.ToString("dd/MM/yyyy");

Cuál.... funciona! ¿Por qué?

Author: Tamir Vered, 2016-01-29

3 answers

Porque Nullable<T> está implementado en C# de una manera que hace que las instancias de esa estructura aparezcan como tipos nullables. Cuando tienes DateTime? es en realidad Nullable<DateTime>, cuando asignas null a eso, estás configurando HasValue a false detrás de escena, cuando compruebas null, estás comprobando HasValue, etc. El operador ?. simplemente se implementa de manera que reemplaza los mismos modismos que funcionan para tipos de referencia también para estructuras nullables. Al igual que el resto del lenguaje hace estructuras nullables similar a los tipos de referencia (con respecto a null - ness).

 20
Author: Joey,
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-01-29 10:29:57

respuesta Corta:

DateTime? es solo una sintaxis dulce para Nullable<DateTime> que no contiene las propiedades y el método de DateTime mientras el operador Elvis trabaja en el not-Nullable Nullable<DateTime>.Value.


Explicación:

El siguiente código:

DateTime? dt = DateTime.Now;
string x;
if (dt != null)
    x = dt?.ToString("dd/MM/yyyy");

Cuando se descompila como C# 5.0 se obtiene el siguiente resultado:

DateTime? nullable = new DateTime?(DateTime.Now);
if (nullable.HasValue)
{
    string str = nullable.HasValue ? nullable.GetValueOrDefault().ToString("dd/MM/yyyy") : null;
}

Nota al margen: el string parece declarado dentro del if es irrelevante debido a la elevación en el nivel MSIL, y dado que el valor no se utiliza más adelante, el descompilador lo muestra como si hubiera sido declarado dentro de ese ámbito if.

Como ves, y dado que DateTime? es solo una sintaxis dulce para Nullable<DateTime>, C# tiene una referencia específica para Nullable<T> s con el operador de Elvis , haciendo su valor de retorno la propia T no anulable.

El resultado del conjunto Elvis operator debe ser Nullable por lo tanto, si desea recibir un valor no-string tendría que ser Nullable<T> o un ReferenceType, pero esto no cambia el hecho de que si el operador ha logrado obtener el valor Nullable<DateTime> por sí mismo, el DateTime devuelto ya no es Nullable<DateTime>.

 14
Author: Tamir Vered,
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-02-01 07:45:45

Considerando:

DateTime? dt = DateTime.Now;
string x;
if(dt != null)
    x = dt.ToString("dd/MM/yyyy");

Aquí dt es una DateTime? o Nullable<DateTime> bruja no es IFormatable y no tiene un método ToString(string format).

Así que tira.

Ahora considerando:

x = dt?.ToString("dd/MM/yyyy");

El ?. es un azúcar sintáctico para:

dt.HasValue ? dt.Value.ToString("dd/MM/yyyy"): null

Aquí dt.Value es una DateTime bruja es IFormatable y tiene un método ToString(string format).

Finalmente la buena manera de escribir el primer código en C# 5.0 es:

DateTime? dt = DateTime.Now;
string x;
if(dt.HasValue)
    x = dt.Value.ToString("dd/MM/yyyy");
 2
Author: Orace,
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-01-29 10:44:54