When I have a nullable long, for example, is there any difference between
myNullableLong.HasValue
and
myNullableLong != null
... or is it just 'syntactic sugar'?
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."
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.
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.
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.
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
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
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.
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