Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there any difference between myNullableLong.HasValue and myNullableLong != null?

Tags:

c#

nullable

When I have a nullable long, for example, is there any difference between

myNullableLong.HasValue 

and

myNullableLong != null

... or is it just 'syntactic sugar'?

like image 726
Fiona - myaccessible.website Avatar asked Mar 08 '11 14:03

Fiona - myaccessible.website


People also ask

Does HasValue check for null?

The compiler replaces null comparisons with a call to HasValue , so there is no real difference. Just do whichever is more readable/makes more sense to you and your colleagues. I would add to that "whichever is more consistent/follows an existing coding style."

What is HasValue?

HasValue indicates whether an instance of a nullable value type has a value of its underlying type. Nullable<T>. Value gets the value of an underlying type if HasValue is true . If HasValue is false , the Value property throws an InvalidOperationException.

What are the nullable types in C#?

The Nullable type is an instance of System. Nullable<T> struct. Here T is a type which contains non-nullable value types like integer type, floating-point type, a boolean type, etc. For example, in nullable of integer type you can store values from -2147483648 to 2147483647, or null value.

What happens when we box or unbox nullable types?

When the nullable type is boxed, the underlying value type is stored in the object, rather than an instance of the nullable type itself. For example, if we box int?, the boxed value will store an int.


3 Answers

It's just syntactic sugar. They will behave exactly the same way - the nullity test actually gets compiled into a call to HasValue anyway.

Sample:

public class Test
{
    static void Main()
    {
        int? x = 0;
        bool y = x.HasValue;
        bool z = x != null;
    }
}

IL:

.method private hidebysig static void  Main() cil managed
{
  .entrypoint
  // Code size       25 (0x19)
  .maxstack  2
  .locals init (valuetype [mscorlib]System.Nullable`1<int32> V_0)
  IL_0000:  ldloca.s   V_0
  IL_0002:  ldc.i4.0
  IL_0003:  call       instance void valuetype [mscorlib]System.Nullable`1<int32>::.ctor(!0)
  IL_0008:  ldloca.s   V_0
  IL_000a:  call       instance bool valuetype [mscorlib]System.Nullable`1<int32>::get_HasValue()
  IL_000f:  pop
  IL_0010:  ldloca.s   V_0
  IL_0012:  call       instance bool valuetype [mscorlib]System.Nullable`1<int32>::get_HasValue()
  IL_0017:  pop
  IL_0018:  ret
} // end of method Test::Main
like image 119
Jon Skeet Avatar answered Oct 20 '22 11:10

Jon Skeet


It's syntactic sugar; Nullable<T> is actually a struct, so it cannot actually be null; the compiler turns calls that compare to null (like your second example) into calls to HasValue.

Note, though, that boxing a Nullable<T> into an object will result in either the value of T (if it has a value) or null (if it doesn't).

I.E.

int? foo = 10; // Nullable<int> with a value of 10 and HasValue = true
int? bar = null; // Nullable<int> with a value of 0 and HasValue = false

object fooObj = foo; // boxes the int 10
object barObj = bar; // boxes null

Console.WriteLine(fooObj.GetType()) // System.Int32
Console.WriteLine(barObj.GetType()) // NullReferenceException
like image 23
Adam Robinson Avatar answered Oct 20 '22 13:10

Adam Robinson


No.

The C# compiler has built-in support for Nullable<T> and will turn equality operations involving null into calls to the struct's members.

n != null and n.HasValue will both compile to identical IL.

like image 3
SLaks Avatar answered Oct 20 '22 13:10

SLaks