2010-09-16 21 views
30

Así que tengo un código que pasa alrededor de este objeto anónimo entre los métodos:C# 4: Dinámico y anulables <>

var promo = new 
{ 
    Text = promo.Value, 
    StartDate = (startDate == null) ? 
     new Nullable<DateTime>() : 
     new Nullable<DateTime>(DateTime.Parse(startDate.Value)), 
    EndDate = (endDate == null) ? 
     new Nullable<DateTime>() : 
     new Nullable<DateTime>(DateTime.Parse(endDate.Value)) 
}; 

Los métodos que reciben este tipo de objeto en el anonimato declaran su tipo que dynamic:

private static bool IsPromoActive(dynamic promo) 
{ 
    return /* check StartDate, EndDate */ 
} 

en tiempo de ejecución, sin embargo, si StartDate o EndDate se establecen para new Nullable<DateTime>(DateTime.Parse(...)), un método que recibe esta dynamic objeto (llamado promo) realiza esto:

if (promo.StartDate.HasValue && promo.StartDate > DateTime.Today || 
    promo.EndDate.HasValue && promo.EndDate < DateTime.Today) 
{ 
    return; 
} 

lanza una excepción:

Server Error in '/' Application. 
'System.DateTime' does not contain a definition for 'HasValue' 

lo que está pasando aquí? ¿Qué no entiendo acerca de los tipos Nullable y la palabra clave dynamic?

Este código funcionaba bien antes de que cambiara Quité el struct que previamente almacenada Text, StartDate y EndDate y lo reemplazó con un tipo anónimo y se lo pasó alrededor mientras dynamic.

+0

Tiene 'promo.StartDate.HasValue', pero al mismo tiempo está usando' promo.StartDate' como si fuera el valor. La incoherencia parece ser un error: use 'promo.StartDate.HasValue' y' promo.StartDate.Value' o promo.StartDate == null' y 'promo.StartDate'. (No sé qué usar, no tengo disponible .NET 4.0 para probar). O ... podría haber un casting implícito, pero no sé si eso es manejado por 'dynamic' muy bien . – strager

+3

No use esa fea sintaxis 'Nullable '; use 'T?' en su lugar :). – Domenic

+1

Descubrimiento interesante, aunque sin tipos dinámicos, tendría que usar HasValue y Value. Pero como el boxeo de tiempo de ejecución elimina la información que se puede anular y deja solo el valor en caja o nulo, no puede usar estas propiedades. Entonces, no use HasValue en absoluto, compare el objeto con nulo en su lugar. – IllidanS4

Respuesta

60

Gran pregunta. Dos hechos que probablemente desconozca:

  1. La dinámica detrás de la escena es solo un objeto. Es decir, una variable "dinámica" es una variable "objeto" con una sugerencia para el compilador que dice "generar operaciones dinámicas en esta variable cuando se usa".

  2. No existe la marca de un nulo. Cuando encasillas un int? para objetar obtienes una referencia de objeto nulo o una int encuadrada. La envoltura de nullable alrededor de int se descarta.

Ahora debe quedar claro lo que está sucediendo aquí. Si promo es dinámico, promo.StartDate es dinámico. Lo que significa que en tiempo de ejecución, es un objeto. Lo que significa que si es de tipo de valor, está encuadrado. Lo que significa que si era nulable, ahora es una referencia nula o un valor enmarcado no anulable. De cualquier manera, esa cosa no tiene una propiedad HasValue. Si desea saber si estaba en su tipo de valor de un tipo de valor que admite valores NULL, entonces verifique si promo.StartDate es nulo o no.

+1

Muy buena respuesta. Ciertamente me iluminó. –

+0

¿Entonces está diciendo que el tiempo de ejecución trata 'Nullable ' especial cuando se trata de 'dynamic'? – strager

+8

@strager: No, eso no es para nada lo que estoy diciendo. El tiempo de ejecución sabe * nada * sobre "dinámico". "dinámico" existe solo en tiempo de compilación.* El tiempo de ejecución trata Nullable como especial al ejecutar una instrucción de boxeo. * –

Cuestiones relacionadas