231

异常描述中有一个悖论: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。我已经删除了ValuefrommyNewDT.MyDateTime但由于生成的设置器而引发了相同的异常。

4

8 回答 8

237

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

您收到的异常是在Nullable.Value的属性中引发的,因为它需要返回 a (因为这是状态的合同),但它不能这样做,因为没有返回,所以它抛出异常。 DateTimeDateTime.ValueDateTime

一般来说,盲目地调用.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);

添加.Valueonother.MyDateTime会导致异常。删除它可以消除异常。我想你找错地方了。

于 2009-12-13T11:14:27.953 回答
18

使用 LINQ 扩展方法(例如Select, Where)时,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
于 2015-01-21T13:23:23.887 回答
8

尝试丢弃.value

DateTimeExtended(DateTimeExtended myNewDT)
{
   this.MyDateTime = myNewDT.MyDateTime;
   this.otherdata = myNewDT.otherdata;
}
于 2009-12-13T11:12:30.773 回答
2

不带部件直接分配成员.Value

DateTimeExtended(DateTimeExtended myNewDT)
{
   this.MyDateTime = myNewDT.MyDateTime;
   this.otherdata = myNewDT.otherdata;
}
于 2009-12-13T11:13:25.970 回答
2

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

this.MyDateTime = newDT.MyDateTime;
于 2009-12-13T11:13:32.487 回答
0

看起来 oldDTE.MyDateTime 是空的,所以构造函数试图取它的值 - 它抛出了。

于 2009-12-13T11:14:43.417 回答
0

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

sName = myObj.Name;

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

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

这行得通。

于 2012-09-28T13:19:36.597 回答
0

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

if (myNewDT.MyDateTime == null)
{
   myNewDT.MyDateTime = DateTime.Now();
}
于 2020-07-08T07:10:22.147 回答