问题
There is paradox in the exception description: Nullable object must have a value (?!)
This is the problem:
I have a DateTimeExtended
class,
that has
{
DateTime? MyDataTime;
int? otherdata;
}
and a constructor
DateTimeExtended(DateTimeExtended myNewDT)
{
this.MyDateTime = myNewDT.MyDateTime.Value;
this.otherdata = myNewDT.otherdata;
}
running this code
DateTimeExtended res = new DateTimeExtended(oldDTE);
throws an InvalidOperationException
with the message:
Nullable object must have a value.
myNewDT.MyDateTime.Value
- is valid and contain a regular DateTime
object.
What is the meaning of this message and what am I doing wrong?
Note that oldDTE
is not null
. I\'ve removed the Value
from myNewDT.MyDateTime
but the same exception is thrown due to a generated setter.
回答1:
You should change the line this.MyDateTime = myNewDT.MyDateTime.Value;
to just this.MyDateTime = myNewDT.MyDateTime;
The exception you were receiving was thrown in the .Value
property of the Nullable DateTime
, as it is required to return a DateTime
(since that's what the contract for .Value
states), but it can't do so because there's no DateTime
to return, so it throws an exception.
In general, it is a bad idea to blindly call .Value
on a nullable type, unless you have some prior knowledge that that variable MUST contain a value (i.e. through a .HasValue
check).
EDIT
Here's the code for DateTimeExtended
that does not throw an exception:
class DateTimeExtended
{
public DateTime? MyDateTime;
public int? otherdata;
public DateTimeExtended() { }
public DateTimeExtended(DateTimeExtended other)
{
this.MyDateTime = other.MyDateTime;
this.otherdata = other.otherdata;
}
}
I tested it like this:
DateTimeExtended dt1 = new DateTimeExtended();
DateTimeExtended dt2 = new DateTimeExtended(dt1);
Adding the .Value
on other.MyDateTime
causes an exception. Removing it gets rid of the exception. I think you're looking in the wrong place.
回答2:
When using LINQ extension methods (e.g. Select
, Where
), the lambda function might be converted to SQL that might not behave identically to your C# code. For instance, C#'s short-circuit evaluated ||
and &&
are converted to SQL's eager AND
and OR
. This can cause problems when you're checking for null in your lambda.
Example:
MyEnum? type = null;
Entities.Table.Where(a => type == null ||
a.type == (int)type).ToArray(); // Exception: Nullable object must have a value
回答3:
Try dropping the .value
DateTimeExtended(DateTimeExtended myNewDT)
{
this.MyDateTime = myNewDT.MyDateTime;
this.otherdata = myNewDT.otherdata;
}
回答4:
In this case oldDTE is null, so when you try to access oldDTE.Value the InvalidOperationException is thrown since there is no value. In your example you can simply do:
this.MyDateTime = newDT.MyDateTime;
回答5:
Assign the members directly without the .Value
part:
DateTimeExtended(DateTimeExtended myNewDT)
{
this.MyDateTime = myNewDT.MyDateTime;
this.otherdata = myNewDT.otherdata;
}
回答6:
Looks like oldDTE.MyDateTime was null, so constructor tried to take it's Value - which threw.
回答7:
I got this message when trying to access values of a null valued object.
sName = myObj.Name;
this will produce error. First you should check if object not null
if(myObj != null)
sName = myObj.Name;
This works.
来源:https://stackoverflow.com/questions/1896185/nullable-object-must-have-a-value