Why System.Nullable?
You must already know, System.Nullable is the only structure that supports the storage of Null as a valid range of values. Generally in case of structures it cannot store null values in it. Say for instance :
Int32 is a structure. When you specify
int x;
It will automatically assign 0 to x. This is same as
int x = default(int);
Generally structures always recursively call default to initialize the value of it. Say for instance :
struct MyCustomStructure { public int m; public int n; }
I have defined a custom structure MyCustomStructure. If you declare an object of it like :
MyCustomStructure myobj;
It will assign myobj to its default. You cannot assign null to myobj. The only way out to this situation is Nullable.
MyCustomStructure myobj = null; //throws exception Nullable<MyCustomStructure> myobj = null; //works fine
Hence you can see, you should always use Nullable for a structure if you want to store the value of null to a structure. For data centric applications, we generally need to keep a variable out of the scope of valid values so that the variable can have a value which might identify the value as nothing. Null is taken as nothing, but in case of normal structures it does not allow us to do that. If you store nothing to an integer, it will automatically initialize to 0. But for any application 0 might be a valid value. So you cannot exclude the 0 from the range of data. Hence you need Nullable to workaround this issue.
How to use Nullable
Nullable is simple. You can declare nullable value types using Nullable
C# 2.0 comes with a new Question mark following data type designator which allows you to declare Nullable type. So,
//Nullable<MyCustomStructure> myobj = null; MyCustomStructure? myobj = null;
Works the same way.
Any Nullable variable has few properties.
- HasValue : Returns true when object has a value in it.
- Value : returns the actual value which is stored within the variable. (this is the object of T)
MyCustomStructure? value = null; bool hasvalue = value.HasValue; bool hasvalue2 = value != null;
Now if you look into the IL for the code it looks like:
.locals init ([0] valuetype [mscorlib]System.Nullable`1<NullableTest.MyCustomStructure> 'value', [1] bool hasvalue, [2] bool hasvalue2) //MyCustomStructure? value = null; IL_0001: ldloca.s 'value' IL_0003: initobj valuetype [mscorlib]System.Nullable`1<NullableTest.MyCustomStructure> //bool hasvalue = value.HasValue; IL_0009: ldloca.s 'value' IL_000b: call instance bool valuetype [mscorlib]System.Nullable`1<NullableTest.MyCustomStructure>::get_HasValue() IL_0010: stloc.1 //bool hasvalue2 = value != null; IL_0011: ldloca.s 'value' //loads a variable onto evaluation stack IL_0013: call instance bool valuetype [mscorlib]System.Nullable`1<NullableTest.MyCustomStructure>::get_HasValue() //calls HasValue IL_001b: stloc.2 //Stores the result in location 2 (hasvalue2)
Clerly you can see the last two lines HasValue and value!=null generates the same thing. So the HasValue checks the value if it is not null and returns the result.
The assignment null to the Nullable Type is same as calling the Default constructor for Nullable.
You can also use Null Coalesce operator for Nullable Types.
int? obj = null; obj = obj ?? -1
Hence you can see the Null Coalesce operator first checks if the object is null. If it is null, it assigns the value -1 to it.
I hope this would help.
Thanks for reading and give your feedback.
The last one is not ternary operator. It is called NullCoalesce operator
ReplyDeleteHmm.. I might be sleeping when I wrote this as Ternary operator.. I have written so many times on Null coalesce operator.
ReplyDeleteThank you for letting me know the mistake.
:)