I noticed something in a code review I did, and am wondering if it's suitable.
a.EndDate.HasValue && a.EndDate > paymentPeriodEndDate
Shouldn’t that be:
a.EndDate.HasValue && a.EndDate.Value > paymentPeriodEndDate
Note, a.EndDate is a DateTime?
, while paymentPeriodEndDate is DateTime
Should .Value be used? Or is it OK to omit it. The compiler allows it, and the code works. I then just wonder why there's a .Value available.
The unary postfix ! operator is the null-forgiving, or null-suppression, operator. In an enabled nullable annotation context, you use the null-forgiving operator to declare that expression x of a reference type isn't null : x! . The unary prefix ! operator is the logical negation operator.
In C#, the compiler does not allow you to assign a null value to a variable.
In statically typed languages, a nullable type is an option type, while in dynamically typed languages (where values have types, but variables do not), equivalent behavior is provided by having a single null value.
C# (pronounced "C-sharp") is an object-oriented programming language from Microsoft that aims to combine the computing power of C++ with the programming ease of Visual Basic. C# is based on C++ and contains features similar to those of Java. C# is designed to work with Microsoft's . NET platform.
A nullable is implicitly castable* to it's underlying type, so
a.EndDate > paymentPeriodEndDate
is implicitly converted to
((DateTime)a.EndDate) > paymentPeriodEndDate
which calls .Value
as part of the cast.
Since you're already done a null-check, then there's no practical difference.
I then just wonder why there's a .Value available.
You would use Value
when there's no way for the compiler to implicitly know what the expected output is (e.g. when passing to a generic method or a method with overloads). Since you're comparing to another DateTime
the compiler can infer your intent and call .Value
for you.
*Techncially I think the compiler adds in a cast since the cast operator from Nullable<T>
to T
is explicit
, but the principle should be the same.
I would use just a.EndDate > paymentPeriodEndDate
here, because your code interpreted as such
a.EndDate.HasValue && a.EndDate > (DateTime?)paymentPeriodEndDate
What you have here is a lifted operator:
For the relational operators
< > <= >=
a lifted form of an operator exists if the operand types are both non-nullable value types and if the result type is
bool
. The lifted form is constructed by adding a single?
modifier to each operand type. The lifted operator produces the valuefalse
if one or both operands are null. Otherwise, the lifted operator unwraps the operands and applies the underlying operator to produce thebool
result.
As result, you have this:
a.EndDate.HasValue && a.EndDate.HasValue && a.EndDate.GetValueOrDefault() > paymentPeriodEndDate
So, you actually double check a.EndDate.HasValue
here.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With