C#4:动态和可空<>

Jus*_*acy 33 c# nullable dynamic

所以我有一些代码在方法之间传递这个匿名对象:

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))
};
Run Code Online (Sandbox Code Playgroud)

接收此匿名对象类型的方法将其类型声明为dynamic:

private static bool IsPromoActive(dynamic promo)
{
    return /* check StartDate, EndDate */
}
Run Code Online (Sandbox Code Playgroud)

在运行时,然而,如果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;
}
Run Code Online (Sandbox Code Playgroud)

它引发了一个异常:

Server Error in '/' Application.
'System.DateTime' does not contain a definition for 'HasValue' 
Run Code Online (Sandbox Code Playgroud)

这里发生了什么?关于Nullable类型和dynamic关键字,我不了解什么?

此代码工作正常之前,我改变了我删除了struct先前存储Text,StartDate以及EndDate与一个匿名类型代替它,传来传去它dynamic.

Eri*_*ert 63

好问题.您可能不知道的两个事实:

  1. 幕后动态只是对象.也就是说,"动态"变量是一个"对象"变量,它带有一个提示编译器的提示,表示"在使用它时对该变量生成动态操作".

  2. 没有箱装可空的东西.当你装一个int?对象你得到一个空对象引用或一个盒装int.int周围的可空包装器被丢弃.

现在应该清楚这里发生了什么.如果促销是动态的,那么promo.StartDate是动态的.这意味着在运行时,它是对象.这意味着如果它是值类型,则将其装箱.这意味着如果它可以为空,则它现在是空引用或盒装非可空值.无论哪种方式,该东西都没有HasValue属性.如果你想知道它的值类型是否可以将null值设置为null,那么检查promo.StartDate是否为null.

  • @strager:不,那根本不是我说的.运行时知道*没有*关于"动态"."dynamic"仅在编译时存在.*运行时在执行装箱指令时将Nullable <T>视为特殊.* (9认同)