4

I have the following code

List<DateTime?> dtDates = new List<DateTime?>()
{
    null,
    DateTime.Today.AddDays(1),
    DateTime.Today.AddDays(-1)
};

IEnumerable<DateTime?> result = dtDates.Where(x => x > DateTime.Today);

Why doesn't it need a nullcheck like x.HasValue && x.Value > DateTime.Today

Here is a simplified version of the issue:

bool dtresult = null < DateTime.Today; 
bool iresult = null < 6;

Is there a nullcheck inside the compare method?

Maksim Simkin
  • 9,561
  • 4
  • 36
  • 49
Toshi
  • 2,532
  • 4
  • 17
  • 45
  • 4
    See https://msdn.microsoft.com/en-us/library/2cf62fcy.aspx: `When you perform comparisons with nullable types, if the value of one of the nullable types is null and the other is not, all comparisons evaluate to false except for != (not equal)` – haim770 Jan 25 '17 at 12:04
  • In most languages, null isn't zero so comparing anything against it returns `False`. That's what `Compare` implements – Panagiotis Kanavos Jan 25 '17 at 12:10
  • That may be true for `Compare`, but the `Compare` methods aren't used for nullable types in this case as the code is rewritten on the outside. The lambda expression will be compiled into a method that first gets `DateTime.Today` and stores it in a local variable, then checks if the passed in value, the `x` is `null`, in which case the result of the method is simply `false`. Only if `x` has a value then its underlying value is obtained through `x.GetValueOrDefault()` before this (which is `DateTime`, not `DateTime?`) is compared to the previously stored value from `DateTime.Today`. – Lasse V. Karlsen Jan 25 '17 at 12:12
  • It is done this way to preserve exceptions from `DateTime.Today`. If `x` is `null`, but reading `DateTime.Today` throws an exception, even if "when `x` is `null` simply return `false`" then the exception will still be thrown because we read `DateTime.Today` before inspecting `x` at all. – Lasse V. Karlsen Jan 25 '17 at 12:13
  • 1
    And no, I cannot write any of this into an answer since the question has been closed. Everything I here describe is due to "lifted operators". The linked duplicate sort-of answers this question and if you arrive there through the link here you should understand that it also covers this case here. – Lasse V. Karlsen Jan 25 '17 at 12:14
  • For comparison operators that compare a nullable type with a non-nullable type (`DateTime? > DateTime` in this case), if the nullable type value is `null` then the result will be `false` for all operators except `!=` which will produce `true`. The operation will be done by first evaluating the right-hand-side (RHS), then checking if LHS is `null`, in which case the result is always `false` (or `true` for `!=`). If LHS is non-`null`, then we compare the underlying value as `LHS.GetValueOrDefault() > RHScopy`. This is done by the compiler. Only then will the `>` operator be used for non-nullable – Lasse V. Karlsen Jan 25 '17 at 12:19
  • @LasseV.Karlsen shouldn't be `bool result = null > -1;` true because `GetValueOrDefault()` retuns `0` in case of `int` – Toshi Jan 25 '17 at 12:24
  • @Toshi: you haven't read Lasses comment carefully. _"...checks if the passed in value, the x is null, in which case the result of the method is simply false..."_ – Tim Schmelter Jan 25 '17 at 12:38
  • If `x` is `null` no further comparison is done, the result is `false`. – Lasse V. Karlsen Jan 25 '17 at 14:47

0 Answers0