Legion
Legion

Reputation: 3447

Why is ReSharper telling me my expression is always true?

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

Answers (4)

Charles Mager
Charles Mager

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

James Thorpe
James Thorpe

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();

enter image description here

Upvotes: 2

sparrow
sparrow

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

Danny van der Kraan
Danny van der Kraan

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

Related Questions