Reputation: 3447
I have this LINQ statement which returns null if the sequence is empty. I assign the result into a nullable DateTime
. Later on I check if the DateTime.HasValue
property and ReSharper tells me the expression is always true.
DateTime? latestUploadDateInBLSO = Documents.Where(d => d.DocumentLinkId == documentLinkId &&
d.UploadedInStage.StageNumber == 6 &&
d.DocumentOwnerTeam.TeamId == AuthorUser.Team.TeamId)
.Select(d => d.UploadedOnDate)
.DefaultIfEmpty()
.Max();
if (latestUploadDateInBLSO.HasValue) { // <-- Says this is always true
Documents.Single(d => d.DocumentLinkId == documentLinkId &&
d.UploadedOnDate == latestUploadDateInBLSO &&
d.UploadedInStage.StageNumber == 6 &&
d.DocumentOwnerTeam.TeamId == AuthorUser.Team.TeamId).IsLatestVersion = true;
}
Since latestUploadDateInBLSO
can be null, how is that expression always true?
Upvotes: 0
Views: 865
Reputation: 26223
As UploadedOnDate
isn't nullable, the result will always be a DateTime
value and never null. If the list is empty, you'll get default(DateTime)
, which is DateTime.MinValue
.
If you want it to return null
, you'll need to cast your UploadedOnDate
to DateTime?
. You can omit the DefaultIfEmpty
as per the docs Max
will return null
for an empty sequence if the type is nullable.
DateTime? latestUploadDateInBLSO = Documents
.Where(d => d.DocumentLinkId == documentLinkId && d.UploadedInStage.StageNumber == 6 && d.DocumentOwnerTeam.TeamId == AuthorUser.Team.TeamId)
.Select(d => (DateTime?)d.UploadedOnDate)
.Max();
Upvotes: 6
Reputation: 32212
It's because of the DefaultIfEmpty
call combined with a sequence of non-nullable elements (DateTime
) - you're saying if the collection returned from the Where
and Select
is empty, to instead return a collection with a single defaulted DateTime
within it, so it will never return null
.
Here's a small sample with the output from LINQPad:
List<DateTime> l = new List<DateTime>();
DateTime x = l.DefaultIfEmpty().Max();
x.Dump();
var y = new DateTime();
y.Dump();
l.DefaultIfEmpty().Dump();
Upvotes: 2
Reputation: 980
DefaultIfEmpty is probably initializing your DateTime object to its default value which is DateTime.MinValue so it's never null and thus HasValue will always return true.
Upvotes: 1
Reputation: 5366
If uploadedOnDate is also of DateTime type then it's not NULL. The default value for DateTime is equal to DateTime.MinValue. That is why your nullable will always have a value. If you want to change this you'll explicitly have to say via DefaultIfEmpty and return NULL as default value.
Upvotes: 3