Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

HasValue and Value

Tags:

c#

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.

like image 514
Craig Avatar asked Mar 09 '15 22:03

Craig


People also ask

What is null forgiving operator?

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.

Can we assign null to int in C#?

In C#, the compiler does not allow you to assign a null value to a variable.

What are nullable data types?

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.

What does it mean in C#?

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.


2 Answers

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.

like image 184
D Stanley Avatar answered Oct 18 '22 22:10

D Stanley


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 value false if one or both operands are null. Otherwise, the lifted operator unwraps the operands and applies the underlying operator to produce the bool 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.

like image 35
user4003407 Avatar answered Oct 18 '22 23:10

user4003407