可空对象必须具有值

时间:2009-12-13 11:08:20

标签: c# nullable invalidoperationexception

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

这是问题所在:

我有一个DateTimeExtended班,

{
  DateTime? MyDataTime;
  int? otherdata;

}

和构造函数

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

运行此代码

DateTimeExtended res = new DateTimeExtended(oldDTE);

使用以下消息抛出InvalidOperationException

  

Nullable对象必须有值。

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

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

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

8 个答案:

答案 0 :(得分:166)

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

您收到的异常被抛入 Nullable .Value DateTime 属性中,因为它需要返回{{ 1}}(因为那是DateTime状态的契约),但它不能这样做,因为没有.Value返回,所以它会引发异常。

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

修改

以下是不会引发异常的.HasValue代码:

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); 上添加.Value会导致异常。删除它摆脱了异常。我觉得你在找错了地方。

答案 1 :(得分:6)

使用LINQ扩展方法(例如SelectWhere)时,lambda函数可能会转换为可能与C#代码行为不同的SQL。例如,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

答案 2 :(得分:5)

尝试删除.value

答案 3 :(得分:2)

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

this.MyDateTime = newDT.MyDateTime;

答案 4 :(得分:1)

直接指定成员而不使用.Value部分:

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

答案 5 :(得分:0)

看起来oldDTE.MyDateTime为null,所以构造函数试图把它的值 - 扔掉。

答案 6 :(得分:0)

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

sName = myObj.Name;

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

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

这很有效。

答案 7 :(得分:0)

我有这个解决方案,它正在为我工​​作

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