2012-04-16 14 views
12

Yo esperaría que los próximos tres líneas de código a ser la misma:usando coalescencia operador nulo en los tipos anulables cambia implícita tipo

public static void TestVarCoalescing(DateTime? nullableDateTime) 
{ 
    var dateTimeNullable1 = nullableDateTime.HasValue ? nullableDateTime : DateTime.Now; 
    var dateTimeNullable2 = nullableDateTime != null ? nullableDateTime : DateTime.Now; 
    var dateTimeWhatType = nullableDateTime ?? DateTime.Now; 
} 

En todos los casos, asigno nullableDateTime a la nueva variable. Esperaría que el tipo de todas las variables se convierta en DateTime? ya que ese es el tipo de nullableDateTime. Pero para mi sorpresa, el tipo de dateTimeWhatType se convierte en DateTime, por lo que no se puede anotar.

Para empeorar las cosas, ReSharper sugiere sustituir la segunda declaración con una expresión nula coalescencia, convirtiéndola en la expresión 3. Así que si dejo que ReSharper haga su trabajo, el tipo de la variable cambiará de DateTime? a DateTime.

De hecho, digamos que en el resto del método, me gustaría utilizar

if (someCondition) dateTimeNullable2 = null; 

que compile bien, hasta que dejo que ReSharper reemplazar la segunda expresión con la versión coalescente nula.

AFAIK, reemplazando

somevar != null ? somevar : somedefault; 

con

somevar ?? somedefault; 

de hecho debe producir el mismo resultado. Pero para la tipificación implícita en un tipo que admite nulos, el compilador parece amenazar ?? como si eso significara.

somevar != null ? somevar.Value : somedefault; 

así que supongo que mi pregunta es ¿por qué el tipo implícito se cambia cuando uso ??, y también donde en la documentación que pude encontrar información sobre esto.

Por cierto, este no es un escenario del mundo real, pero me gustaría saber por qué el uso de ?? cambia el tipo (implícito).

+3

¿Por qué esperaría 'nullableDateTime ?? DateTime.Now' para producir un 'DateTime?', Cuando el compilador tiene suficiente información para saber que el resultado nunca será 'nulo'? –

+0

@Damien: en mi primer y segundo ejemplo, el compilador también tiene información suficiente para saber que el resultado nunca será 'nulo'. Esa es exactamente la razón por la que encuentro este comportamiento algo extraño. – comecme

+1

Pero '?: 'admite un rango mucho más grande de posibles entradas (no hay ninguna razón para que la 'condición' deba conectarse a cualquiera de las 'expresiones' de resultados). Como tal, sería inusual que el compilador fuera diseñado para realizar este análisis contra '?:'. Mientras que, para '??', sabe exactamente que el resultado será la primera expresión sin posibilidad de que esa expresión sea nula, o la segunda expresión. –

Respuesta

6

Los dos primeros ejemplos te están llevando por mal camino; mejor habría que considerar no su sección de 7,12

var dateTimeNullable1 = nullableDateTime.HasValue 
    ? nullableDateTime 
    : DateTime.Now; 

sino

var dateTimeNullable1 = nullableDateTime.HasValue 
    ? nullableDateTime.Value 
    : DateTime.Now; 

de la cotización "El operador coalescente nula" de la especificación C# 3.0 (disculpas para el formato ligeramente chungo):

el tipo de la expresión a ?? b depende de que implícitas conversiones son AvaI lable entre los tipos de los operandos.Con el fin de preferencia, del tipo de a ?? b es A0, A, o B, donde A es el tipo de a, B es el tipo de b (siempre que b tiene un tipo), y A0 es el tipo subyacente de A si A es un tipo que admite nulo, o A de lo contrario.

Así que si a es Nullable<Something> y b se puede convertir implícitamente a Something, el tipo de la expresión entera será Something. Como sugiere @Damien_The_Unbeliever, el punto de este operador fusionará nulos.

+1

Hasta ahora solo había buscado en [la documentación de MSDN en '??'] (http://msdn.microsoft.com/en-us/library/ms173224.aspx) y [Usando tipos Nullable] (http: // msdn .microsoft.com/es-us/library/2cf62fcy.aspx). Nunca usan 'var' en esos ejemplos, pero asignan a un tipo explícito. De todos modos, aparentemente 'a ?? b' es ** no ** exactamente lo mismo que 'a! = nulo? a: b' cuando se trata de tipos anulables. – comecme

5

Para ser un abogado de todos los idiomas, por un momento. Desde el C# spec (versión 4):

7,13

El tipo de la expresión a ?? b depende de que las conversiones implícitas están disponibles en los operandos. En orden de preferencia, del tipo de a ?? b es A0, A, o B, donde A es el tipo de a (siempre que a tiene un tipo), B es el tipo de b (siempre que b tiene un tipo), y A0 es el tipo subyacente de A si A es un tipo anulable, o A de lo contrario.

Por lo tanto, ?? se define explícitamente para preferir el tipo subyacente de la primera expresión, si esa primera expresión es de tipo anulable.

Considerando que la lengua de 7,14 (que trata de ?:) sólo se analizan los tipos reales de x y y, de la forma b ? x : y, y discute implícitas conversiones entre estos dos tipos.

Si una conversión implícita (apartado 6.1) existe de X a Y, pero no de Y a X, entonces Y es el tipo de la expresión condicional

Desde Nullable(T) define una implícita conversión desde T hasta Nullable(T), y solo conversión explícita de Nullable(T) a T, el único tipo posible de la expresión general es Nullable(T).

Cuestiones relacionadas