可为空的对象必须有一个值
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扩展方法(例如Select
, Where
)时,lambda函数可能会转换为SQL,这可能与您的C#代码行为不同。 例如,C#的短路评估||
和&&
都被转换成SQL的AND
和OR
。 当你在你的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;
这工作。