HasValue и Value

Я заметил что-то в обзоре кода, который я сделал, и мне интересно, подходит ли оно.

a.EndDate.HasValue && a.EndDate > paymentPeriodEndDate

Должно быть:

a.EndDate.HasValue && a.EndDate.Value > paymentPeriodEndDate

Примечание. a.EndDate является DateTime?, а paymentPeriodEndDate - DateTime

Должен ли использоваться. Или это нормально, чтобы опустить это. Компилятор позволяет это, и код работает. Тогда я просто задаюсь вопросом, почему есть доступная. [/P >

Ответ 1

NULL-значение неявно литерируется * его базовому типу, поэтому

a.EndDate > paymentPeriodEndDate

неявно преобразуется в

((DateTime)a.EndDate) > paymentPeriodEndDate

который вызывает .Value как часть роли.
Поскольку вы уже сделали нулевую проверку, тогда нет никакой практической разницы.

Тогда я просто удивляюсь, почему есть доступная.

Вы использовали бы Value, когда компилятор не смог бы точно знать, каков ожидаемый результат (например, при передаче общего метода или метода с перегрузками). Поскольку вы сравниваете с другим DateTime, компилятор может вывести ваше намерение и вызвать .Value для вас.


* Технически я думаю, что компилятор добавляет в литье, поскольку оператор трансляции от Nullable<T> до T равен explicit, но принцип должен быть одинаков.

Ответ 2

Я бы использовал только a.EndDate > paymentPeriodEndDate здесь, потому что ваш код интерпретировался как таковой

a.EndDate.HasValue && a.EndDate > (DateTime?)paymentPeriodEndDate

Здесь у вас есть оператор с поднятым:

  • Для реляционных операторов

    <  >  <=  >= 
    

    существует допустимая форма оператора, если типы операндов являются неинифицируемыми типами значений и если тип результата равен bool. Приподнятая форма строится путем добавления единственного модификатора ? к каждому типу операнда. Поднятый оператор выдает значение false, если один или оба операнда равны нулю. В противном случае снятый оператор разворачивает операнды и применяет основной оператор для получения результата bool.

В результате у вас есть следующее:

a.EndDate.HasValue && a.EndDate.HasValue && a.EndDate.GetValueOrDefault() > paymentPeriodEndDate

Итак, вы на самом деле дважды проверяете a.EndDate.HasValue здесь.

Ответ 3

Вы можете опустить .Value, потому что если a.EndDate не будет иметь значения, тогда сравнение всегда будет возвращать false.

Но в вашем коде вы проверяете, имеет ли он значение сначала, поэтому можно предположить, что сравнение вернет точный результат, а не false, который исходит из одного аргумента, не имеющего значения.

В терминах сгенерированного кода IL они, вероятно, будут почти одинаковыми, поэтому нет никакого эффекта или что-то подобное.