Adding Nullables To Your Code
Why should I use Nullables? What are they for? Why have they added the Nullables to the .Net Framework 2.0?
These are questions I asked myself. And because you are good people, I will share my thoughts with you. Isn't it wonderful? Nah! I'm just kidding. In fact, the following post is the product of some readings on the topic and I started using it in my day-to-day coding because it answered a real issue.
First thing first. Let's consider the following scenario: a form on a web page somehow bound to a database. On the form, there are several kind of inputs: textboxes, dropdownlists, radiobuttons, checkboxes, textboxes for date/time and so on. What if some fields are not mandatory? It means these fields may be left empty. How should you treat an empty field considering that the database accepts null values?
How do you manage the situation? Because, philosophically speaking, an absence of value is a value. It means the user did not want to add his input, for any reason, on the form.
With value types however, how could you move that piece of information from the form to the database knowing value types cannot be null (C#).
A Value type cannot be null because its value is not a pointer to an address in memory but the value itself. Whereas the reference type is a pointer to an address in memory. A null value represents an address in memory, x00000000. So setting a reference type to null is in fact pointing to an address in memory. When times come to instantiate the object, the pointer is redirected to the address in memory where the object is (somewhere on the heap).
There have been some thoughts spent over this to overcome the impossibility of assigning a null value to value types. Some have thought about adding a bite to all value types where this extra bit would serve as a flag to indicate whether or not the value is null. Although this possibility seems sexy, it seems it would have been a nightmare to manage and moreover to validate the flag whenever accessing its value. For instance, what if a Byte could have an extra bite to flag its has a null value. By definition, a Byte is defined with 256 possibilities ranging from 0 to 255 (00 to FF). An extra bite would mean 257 possibilities (there is the nightmare).
Another way to represent the null value is to use a default values throughout the application. The problem with this approach is to select a value that will be never use.
A third way is to wrap the value type in a reference type, such like the Object class or a custom class. Although it seems practical, it is however costly on memory and performance.
With the coming of the .NET Framework 2.0 and the Generics, the Framework addresses this issue with the Nullable<T> type. This type is a Generic class with a type value constraint. Since only type values can not be null, it makes sense.
Let's see how we can use the Nullable<t> Type:
1: public static void ShowNullable()
2:{
3: //Nullable<T> aInt = null;
4: Nullable<int> aInt = null;
5:
6: try
7: {
8: int assignerInt = aInt.Value;
9: }
10: catch (InvalidOperationException ex)
11: {
12: Console.WriteLine("Exception of type
InvalidOperationException: {0}", ex.Message);
13: }
14: catch (Exception ex)
15: {
16: Console.WriteLine("Exception de type
System.Exception: {0}", ex.Message);
17: }
18:
19: //Using the HasValue property
20: if (aInt.HasValue)
21: Console.WriteLine("Value: {0}", aInt);
22: else
23: Console.WriteLine("Value: null");
24:
25: //Using GetValueOrDefault
26: Console.WriteLine("Default value (with a parameter):
{0}", aInt.GetValueOrDefault(-5));
27: Console.WriteLine("Default value (without a parameter):
{0}", aInt.GetValueOrDefault());
28:}
On line 4), we see how a Nullable can be declared. Like Generics, the Nullable is fully qualified with a type parameter specified between angle brackets. The initial value of aInt is null. When you try to retrieve a Nullable value having a null value, it throws an InvalidOperatorException. To prevent the exception from being thrown, it is best to test the Nullable with the HasValue property. The property returns false when it has null as a value. You can process the value according to it. Another feature of the Nullable is the GetValueOrDefault where it returns a default value when the Nullable is null. You have the choice to assign yourself the default value to be returned in case the Nullable is null, or you let the Framework return the default value (0, false, date.MinVale, and so on).
For C# users, there are two things worth mentioning. First is the shortcut for declaring a Nullable. The other is the shorcut for the GetValueOrDefault method. Let's have a look at the following code sample:
1: public static void ShowNullableOperators()
2: {
3: Nullable<int> a = 1;
4: int? b = null;
5: int? c = null;
6: c = a ?? 3;
7: Console.WriteLine("Value of a: {0};
Value of b: {1},
Value of c with operator ??: {2}", a, b, c);
8: a = null;
9: c = a ?? 3;
10: Console.WriteLine("Value of a: {0};
Value of b: {1},
Value of c with operator ??: {2}", a, b, c);
11: }
On line 3), it is the usual Nullable declaration. On the next line, it is the shortcut for declaring a nullable. In this example, I have declare a Nullable of type int. I also assigned a null value to it. On the sixth line, it is the default value comparator. This operator first evaluate the left argument, in this case a, to determine if it has a null value. If it is not a null value, it returns the value. Otherwise, it returns the right value.
Conclusion
The Nullable type is a convenient type to use when a real type may be assigned to a null value. The few properties available are significant and useful. The HasValue property gives the opportunity to the programmer to decide the logic to be applied in the case of a null value. If no logic is required, the GetValueOrDefault method is a good alternative.
This post concludes the topics I covered four weeks ago in a lunch meeting. As you can see, there was a lot of stuff but it was a good study that covered some of the most important new features in .NET Framework 2.0.
Cheers!
Patrice