可空对象必须有一个值

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

这就是问题所在:

我有一个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而抛出相同的异常。

371595 次浏览

尝试删除.value

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

直接分配成员,不需要.Value部分:

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

在本例中,oldDTE为空,因此当您尝试访问oldDTE时。值抛出InvalidOperationException,因为没有值。在你的例子中,你可以简单地这样做:

this.MyDateTime = newDT.MyDateTime;

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

你接收到的异常是在可以为空 DateTime.Value属性中抛出的,因为它需要返回一个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);

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

看起来像老古董。MyDateTime为空,所以构造函数试图取它的值-抛出。

当我试图访问空值对象的值时,我得到了这条消息。

sName = myObj.Name;

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

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

这个作品。

当使用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

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

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