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 они, вероятно, будут почти одинаковыми, поэтому нет никакого эффекта или что-то подобное.