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


189

异常描述中存在悖论:可空对象必须具有值(?!)

这就是问题:

我有一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。我从中删除了ValuemyNewDT.MyDateTime但由于生成了setter而引发了相同的异常。


什么是其他构造函数?
Paul Creasey

奇怪。我在此处使用.Value复制异常,而在此处使用.Value复制没有异常。您确定您正在运行更新的代码吗?
Yuliy

构造函数采用自身的一个实例。您如何创建第一个实例?
Paul Creasey

它被构造为没有参数的new(),然后添加值(它可以正常工作)。
Dani

6
问题已解决-问题不存在... otherdata和MyDateTime生成了一个setter,它在设置值之前正在检查该值。
Dani

Answers:


201

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

您正在接收的异常被抛出.ValueNullable 的属性中DateTime,因为它需要返回一个DateTime(因为这是.Value各州之间的约定),但是它不能这样做,因为没有DateTime返回值,因此它引发了一个异常。

通常,盲目调用.Value可为null的类型是一个坏主意,除非您事先了解该变量必须包含一个值(即通过.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);

添加.Valueon other.MyDateTime会导致异常。删除它摆脱了异常。我认为您在找错地方了。


您对.value是正确的,但其他原因会导致异常。我删除了.value,并且更改了构造函数的代码顺序-首先复制int值,但会引发相同的异常。
Dani

我对这个问题发表了评论-找到了问题,它在属性的生成的setter中。
Dani

是的,它解决了我的问题,我只是将可空对象更改为不可空对象,并将datetime直接转换为字符串,而不是通过datetimeobject.value.datetime.tostring()
adnan 2016年

好答案。.Value(我想)获得对空对象进行调用的异常是有道理的,但是如果您碰巧正在处理两个Nullable对象,则异常消息确实会产生误导。诸如“ .Value属性要求对象为非空”之类的东西会更有意义。
DVK

9

当使用LINQ扩展方法(例如SelectWhere),lambda函数可以被转换为SQL可能不完全相同的行为对你的C#代码。例如,C#的短路评估&&||转换为SQL的eager ANDOR。当您在lambda中检查null时,这可能会导致问题。

例:

MyEnum? type = null;
Entities.Table.Where(a => type == null || 
    a.type == (int)type).ToArray();  // Exception: Nullable object must have a value

5
我知道此答案与OP的具体情况无关,但与他得到的Exception有关。另外,该页面是该异常在Google上的第一匹配,因此非常相关。
保护者

6

尝试删除 .value

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

没有帮助。如果我先运行第二行,它将引发相同的异常。
Dani

2

在这种情况下,oldDTE为null,因此,当您尝试访问oldDTE.Value时,由于没有值,将引发InvalidOperationException。在您的示例中,您可以简单地执行以下操作:

this.MyDateTime = newDT.MyDateTime;

oldDTE不为null,但是无论如何我都删除了该值...它仍然引发该异常...。–
Dani

1

直接分配没有成员的成员.Value

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


0

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

sName = myObj.Name;

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

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

这可行。


1
在回答之前,请先尝试通读该问题的其他答案-特别是已接受的答案,该答案准确说明了您在答案中所放的内容。尽管它没有使用代码显示它,但却将其拼写出来。另外,尽量让你的示例代码相关的问题的-比如this.MyDateTime = myNewDT.MyDateTime.Value;,不sName = myObj.Name;
newfurniturey
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.