可为空的对象必须有一个值

exception描述中有一个悖论:可为空的对象必须有一个值(?!)

这就是问题:

我有一个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会引发同样的exception。

你应该改变这一行this.MyDateTime = myNewDT.MyDateTime.Value; 只是this.MyDateTime = myNewDT.MyDateTime;

你收到的exception是在Nullable DateTime的.Value属性中抛出的,因为它需要返回一个DateTime(因为这是.Value状态的合同),但是它不能这样做,因为没有DateTime返回,所以它会抛出一个exception。

一般来说,在可空types上盲目地调用.Value是一个坏主意,除非你有一些事先知道该variables必须包含一个值(即通过HasValue检查)。

编辑

这是DateTimeExtended的代码,不会抛出exception:

 class DateTimeExtended { public DateTime? MyDateTime; public int? otherdata; public DateTimeExtended() { } public DateTimeExtended(DateTimeExtended other) { this.MyDateTime = other.MyDateTime; this.otherdata = other.otherdata; } } 

我testing它是这样的:

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

在other.MyDateTime上添加.Value会导致exception。 删除它摆脱了例外。 我想你在错误的地方看。

尝试删除。值

直接指定成员,不带.Value部分:

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

在这种情况下,oldDTE为空,因此当您尝试访问oldDTE.Value时,将抛出InvalidOperationException,因为没有值。 在你的例子中,你可以简单地做:

 this.MyDateTime = newDT.MyDateTime; 

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

看起来像oldDTE.MyDateTime是空的,所以构造函数试图把它的价值 – 投掷。

尝试访问空值对象的值时,我收到了这条消息。

 sName = myObj.Name; 

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

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

这工作。