【问题标题】:nullable object must have a value可空对象必须有一个值
【发布时间】:2010-12-26 03:42:31
【问题描述】:

异常描述中存在悖论: 可空对象必须有一个值 (?!)

这就是问题所在:

我有一个DateTimeExtended 课程, 有

{
  DateTime? MyDataTime;
  int? otherdata;

}

还有一个构造函数

DateTimeExtended(DateTimeExtended myNewDT)
{
   this.MyDateTime = myNewDT.MyDateTime.Value;
   this.otherdata = myNewDT.otherdata;
}

运行此代码

DateTimeExtended res = new DateTimeExtended(oldDTE);

抛出一个带有消息的InvalidOperationException

可空对象必须有一个值。

myNewDT.MyDateTime.Value - 有效并且包含一个常规的DateTime 对象。

这条消息的含义是什么,我做错了什么?

注意oldDTE 不是null。我已经从myNewDT.MyDateTime 中删除了Value,但是由于生成的setter 引发了同样的异常。

【问题讨论】:

  • 另一个构造函数是什么?
  • 奇怪。我在那里用 .Value 重现异常,没有 .Value 那里没有异常。您确定您正在运行更新后的代码吗?
  • 构造函数接受一个自身的实例。你是如何创建第一个实例的?
  • 它被构造为没有参数的 new(),然后我添加了值(它有效)。
  • 问题已解决 - 问题不存在...生成了其他数据和 MyDateTime 的设置器,它在设置它之前检查值.. 当它为空时飞行!!!跨度>

标签: c# nullable invalidoperationexception


【解决方案1】:

您应该将行 this.MyDateTime = myNewDT.MyDateTime.Value; 更改为 this.MyDateTime = myNewDT.MyDateTime;

您收到的异常是在 Nullable DateTime.Value 属性中引发的,因为它需要返回 DateTime(因为那是.Value 的合同规定了什么),但它不能这样做,因为没有 DateTime 可以返回,所以它会引发异常。

一般来说,在可空类型上盲目调用.Value 是个坏主意,除非您事先知道该变量必须 包含一个值(即通过 @ 987654329@ 检查)。

编辑

这是DateTimeExtended 的代码,它不会引发异常:

class DateTimeExtended
{
    public DateTime? MyDateTime;
    public int? otherdata;

    public DateTimeExtended() { }

    public DateTimeExtended(DateTimeExtended other)
    {
        this.MyDateTime = other.MyDateTime;
        this.otherdata = other.otherdata;
    }
}

我是这样测试的:

DateTimeExtended dt1 = new DateTimeExtended();
DateTimeExtended dt2 = new DateTimeExtended(dt1);

other.MyDateTime 上添加.Value 会导致异常。删除它可以消除异常。我想你找错地方了。

【讨论】:

  • 您对 .value 的看法是正确的,但其他原因会导致异常。我已经删除了 .value,并且我已经更改了构造函数的代码顺序 - 首先复制 int 值,但抛出了相同的异常。
  • 我已经评论了这个问题 - 发现了问题,它在为属性生成的设置器中。
  • 是的,它解决了我的问题,我只是将可空对象更改为不可空对象,并将日期时间直接转换为字符串,而不是通过 datetimeobject.value.datetime.tostring()
  • 很好的答案。在 null 对象上调用 .Value 的异常是有道理的(我猜),但是如果您碰巧正在处理两个 Nullable 对象,则异常消息确实会产生误导。像“.Value 属性要求对象为非空”之类的东西会更有意义。
【解决方案2】:

使用 LINQ 扩展方法(例如 SelectWhere)时,lambda 函数可能会转换为 SQL,其行为可能与您的 C# 代码不同。例如,C# 的短路评估 &&|| 被转换为 SQL 的急切 ANDOR。当您在 lambda 中检查 null 时,这可能会导致问题。

例子:

MyEnum? type = null;
Entities.Table.Where(a => type == null || 
    a.type == (int)type).ToArray();  // Exception: Nullable object must have a value

【讨论】:

  • 我意识到这个答案与 OP 的具体情况无关,但与他得到的异常有关。此外,此页面是该异常在 Google 上的第一次点击,这使其具有相关性。
【解决方案3】:

尝试删除 .value

DateTimeExtended(DateTimeExtended myNewDT)
{
   this.MyDateTime = myNewDT.MyDateTime;
   this.otherdata = myNewDT.otherdata;
}

【讨论】:

  • 没有帮助。如果我先运行第二行,它会抛出相同的异常。
【解决方案4】:

不带.Value 部分直接分配成员:

DateTimeExtended(DateTimeExtended myNewDT)
{
   this.MyDateTime = myNewDT.MyDateTime;
   this.otherdata = myNewDT.otherdata;
}

【讨论】:

    【解决方案5】:

    在这种情况下,oldDTE 为 null,因此当您尝试访问 oldDTE.Value 时,会抛出 InvalidOperationException,因为没有值。在您的示例中,您可以简单地执行以下操作:

    this.MyDateTime = newDT.MyDateTime;
    

    【讨论】:

    • oldDTE 不为空,但无论如何我删除了该值......它仍然抛出该异常......
    【解决方案6】:

    看起来 oldDTE.MyDateTime 为空,因此构造函数试图获取它的值 - 它抛出了。

    【讨论】:

      【解决方案7】:

      我在尝试访问空值对象的值时收到此消息。

      sName = myObj.Name;
      

      这会产生错误。首先你应该检查对象是否不为空

      if(myObj != null)
        sName = myObj.Name;
      

      这行得通。

      【讨论】:

      • 在回答之前,请先尝试通读该问题的其他答案 - 尤其是接受的答案,该答案准确地说明了您在 your 答案中放置的内容。虽然它没有使用代码显示它,但它拼写出来。另外,尝试使您的示例代码与问题相关 - 例如this.MyDateTime = myNewDT.MyDateTime.Value;,而不是sName = myObj.Name;
      【解决方案8】:

      我得到了这个解决方案,它对我有用

      if (myNewDT.MyDateTime == null)
      {
         myNewDT.MyDateTime = DateTime.Now();
      }
      

      【讨论】:

        猜你喜欢
        • 2012-02-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-05-20
        • 1970-01-01
        相关资源
        最近更新 更多