异常描述中有一个悖论:Nullable object must have a value (?!)
这就是问题:
我有一个 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 引发了相同的异常。
您应该将第 this.MyDateTime = myNewDT.MyDateTime.Value;
行更改为 this.MyDateTime = myNewDT.MyDateTime;
您收到的异常是在 Nullable DateTime
的 .Value
属性中引发的,因为它需要返回一个 DateTime
(因为这就是合同对于 .Value
个状态),但它不能这样做,因为没有 DateTime
可以返回,因此它会引发异常。
一般来说,对可空类型盲目调用 .Value
是个坏主意,除非您事先知道该变量 必须 包含一个值(即通过 .HasValue
< /strong> 检查)。
编辑
以下是不引发异常的 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
会导致异常。删除它可以消除异常。我想你找错地方了。
使用 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
尝试删除 .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.Value 时,会抛出 InvalidOperationException,因为没有值。在您的示例中,您可以简单地执行以下操作:
this.MyDateTime = newDT.MyDateTime;
看起来 oldDTE.MyDateTime 是空的,所以构造函数试图取它的值 - 它抛出了。
尝试访问空值对象的值时收到此消息。
sName = myObj.Name;
这会产生错误。首先你应该检查对象是否不为空
if(myObj != null)
sName = myObj.Name;
这行得通。
this.MyDateTime = myNewDT.MyDateTime.Value;
,而不是 sName = myObj.Name;
我得到了这个解决方案,它对我有用
if (myNewDT.MyDateTime == null)
{
myNewDT.MyDateTime = DateTime.Now();
}
.Value
异常是有道理的(我猜),但是如果您碰巧正在处理两个 Nullable 对象,那么异常消息确实会产生误导。像“.Value 属性要求对象为非空”之类的东西会更有意义。