【问题标题】:There is no implicit conversion between null and datetime [duplicate]null 和 datetime 之间没有隐式转换 [重复]
【发布时间】:2013-12-22 07:42:30
【问题描述】:

以下代码从给定的DataRow(modelValue) 中读取一条数据并将其解析为nullableDateTime 实例。

问题:请参阅L1 & L2 下的代码部分,其中两者在技术上是相等的(如果我没有犯任何小学生错误)。但是,L1 可以按预期工作,但L2 不能正常工作。我得到了

null 和 datetime 之间没有隐式转换

当我执行L2 下的代码时。有人可以给我建议吗?

        DateTime? CallBack;

        var callBackDate = modelValue["CallBack"] == DBNull.Value ? null : modelValue["CallBack"].ToString();
        //Parsing
        DateTime cdate;
        if (!DateTime.TryParse(callBackDate, out cdate))
            cdate = DateTime.MinValue;


        //L1
        if (cdate==DateTime.MinValue)
            CallBack = null;
        else
           CallBack = cdate.Date;

       //L2  
       CallBack = cdate == DateTime.MinValue?null:cdate.Date;

【问题讨论】:

  • 这已经被很多人问过了,例如here。 IMO,仍然使用?: 的最干净的解决方法是... ? default(DateTime?) : ...
  • 编译器无法推断出表达式cdate == DateTime.MinValue?null:cdate.Date 应该返回DateTime? 而不是DateTime(因为cdate.DateDateTime)。因此,它尝试将 null 转换为 DateTime... 并失败。

标签: c#


【解决方案1】:

您需要告诉编译器 null 应该被视为DateTime?。否则编译器不知道null 是什么类型。

CallBack = cdate == DateTime.MinValue ? (DateTime?)null : cdate.Date;

【讨论】:

  • "否则编译器不知道 null 是什么类型。"这不是这里的问题。如果第三个操作数是引用类型或可为空的类型,而不是不可为空的值类型,则相同的表达式将起作用。问题是null和DateTime之间没有隐式转换。
  • @Jakub Konecki,请参阅代码部分 L1 和 L2,两者在技术上是相同的,我认为 csc.exe 对这两个部分使用相同的编译风格。另外,如果我同意你的结果,那么 DateTime 怎么样? dt=null 工作正常(无论您是在方法中还是作为字段声明它)?我们在这里没有做任何明确的强制转换。
  • @Nair 编译器试图将null 转换为DateTime,而不是DateTime?。是的,它可以将null 转换为DateTime?
  • @Nair 看到我的回答,我解释了为什么编译器无法评估表达式。
【解决方案2】:
(Z) ? X : Y

三元运算符要求存在从第二个操作数 (X) 到第三个操作数 (Y) 或从 Y 到 X 的隐式转换。

由于null 无法隐式转换为DateTimeDateTime 也无法隐式转换为null,因此无法计算表达式。更多信息:Type inference woes by Eric Lippert

您必须将null 转换为DateTime?。通过这样做,X 将是 DateTime? 类型,Y 将是 DateTime 类型。由于存在从DateTimeDateTime? 的隐式转换,因此可以计算表达式,并且它将返回DateTime? 类型的值。

或者,按照相同的逻辑,您也可以将第三个操作数 Y 强制转换为 DateTime?

【讨论】:

    【解决方案3】:

    为什么不首先使用支持可空类型的DataRow.Field 扩展方法?

    DateTime? CallBack = modelValue.Field<DateTime?>("CallBack");
    

    但由于您实际上有一个 string 列,您需要先对其进行解析:

    DateTime? CallBack = null;
    string callBackDate = modelValue.Field<string>("CallBack");
    if(!string.IsNullOrWhiteSpace(callBackDate))
    {
        DateTime cdate;
        if(DateTime.TryParse(callBackDate, out cdate))
            CallBack = cdate;
    }
    

    就是这样。

    【讨论】:

    • 虽然我的问题与我的问题不同,但它很方便。谢谢
    • @Nair:我已经编辑了我的答案以提供正确的解析。
    【解决方案4】:

    您可以执行以下操作:

            DateTime aDateTime = DateTime.MinValue;
            DateTime? aNullableDateTime = aDateTime == DateTime.MinValue ? null : new DateTime?(aDateTime.Date);
    

    它使用 Nullable(Of T) 结构。

    【讨论】:

      猜你喜欢
      • 2015-07-14
      • 2010-11-19
      • 2023-03-17
      • 2015-11-25
      • 1970-01-01
      • 1970-01-01
      • 2013-09-01
      • 2019-06-21
      • 2012-03-13
      相关资源
      最近更新 更多