所以我有一些代码在方法之间传递这个匿名对象:
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))
};
接收此匿名对象类型的方法将其类型声明为dynamic
:
private static bool IsPromoActive(dynamic promo)
{
return /* check StartDate, EndDate */
}
但是,在运行时,如果StartDate
或EndDate
设置为new Nullable<DateTime>(DateTime.Parse(...))
,则会收到此dynamic
对象(名为promo
)的方法执行此操作:
if (promo.StartDate.HasValue && promo.StartDate > DateTime.Today ||
promo.EndDate.HasValue && promo.EndDate < DateTime.Today)
{
return;
}
它抛出异常:
Server Error in '/' Application.
'System.DateTime' does not contain a definition for 'HasValue'
这里发生了什么?关于Nullable
类型和dynamic
关键字,我不了解哪些内容?
此代码在我更改之前工作正常我删除了先前存储struct
,Text
和StartDate
的{{1}},并将其替换为匿名类型并将其传递为EndDate
。
答案 0 :(得分:63)
好问题。您可能不知道的两个事实:
幕后动态只是对象。也就是说,“动态”变量是一个“对象”变量,带有一个提示编译器的提示,说明“在使用它时对该变量生成动态操作。”
没有箱装可空的东西。当你装一个int?对象你得到一个空对象引用或一个盒装int。 int周围的可空包装器被丢弃。
现在应该清楚这里发生了什么。如果促销是动态的,那么promo.StartDate是动态的。这意味着在运行时,它是对象。这意味着如果它是值类型,则将其装箱。这意味着如果它可以为空,则它现在是空引用或盒装非可空值。无论哪种方式,该东西都没有HasValue属性。如果你想知道它的值类型是否可以将null值设置为null,那么检查promo.StartDate是否为null。