Pages

Saturday, September 4, 2010

Notion of System.Nullable - A Look

I love C# as a language. It has lots of flexibilities and hooks to turn around things that was impossible for other languages. One of such thing is the introduction of Nullable Types. In this post,  I will discuss how you could use Nullable to make sure your code works well for null values in Value Types.

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 and start using it. The default(Nullable) is null. I have already showed you how you could declare a nullable type. 
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.
  1. HasValue : Returns true when object has a value in it. 
  2. Value : returns the actual value which is stored within the variable. (this is the object of T)
Lets look into HasValue :
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.

2 comments:

  1. The last one is not ternary operator. It is called NullCoalesce operator

    ReplyDelete
  2. Hmm.. I might be sleeping when I wrote this as Ternary operator.. I have written so many times on Null coalesce operator.

    Thank you for letting me know the mistake.
    :)

    ReplyDelete

Please make sure that the question you ask is somehow related to the post you choose. Otherwise you post your general question in Forum section.