2.6. Make Simple Data Types Nullable
With the new support for generics that's found in the .NET Framework, a number of new features become possible. One of these featuresgeneric strongly typed collectionswas demonstrated in the previous lab, "Build Typesafe Generic Classes." Now you'll see another way that generics can solve common problems, this time by using the new nullable data types.
Note: Do you need to represent data that may or may not be present? VB . NET's new nullable types fill the gap.
2.6.1. How do I do that?
A null value (identified in Visual Basic by the keyword Nothing), is a special flag that indicates no data is present. Most developers are familiar with null object references, which indicate that the object has been defined but not created. For example, in the following code, the FileStream contains a null reference because it hasn't been instantiated with the New keyword:
Dim fs As FileStream If fs Is Nothing ' This is always true because the FileStream hasn't ' been created yet. Console.WriteLine("Object contains a null reference.") End If
Core data types like integers and strings can't contain null values. Numeric variables are automatically initialized to 0. Boolean variables are False. String variables are set to an empty string (''") automatically. In fact, even if you explicitly set a simple data type variable to Nothing in your code, it will automatically revert to the empty value (0, False, or ""), as the following code demonstrates:
Dim j As Integer = Nothing If j = 0 Then ' This is always true because there is an ' implicit conversion between Nothing and 0 for integers. Console.WriteLine("Non-nullable integer j = " & j) End If
This design sometimes causes problems, because there's no way to distinguish between an empty value and a value that was never supplied in the first place. For example, imagine you create code that needs to retrieve the number of times the user has placed an order from a text file. Later on, you examine this value. The problem occurs if this value is 0. Quite simply, you have no way to know whether this is valid data (the user placed no orders), or it represents missing information (the setting couldn't be retrieved or the current user isn't a registered customer).
Thanks to generics, .NET 2.0 has a solutiona System.Nullable class that can wrap any other data type. When you create an instance of Nullable you specify the data type. If you don't set a value, this instance contains a null reference. You can test whether this is true by testing the Nullable.HasType( ) method, and you can retrieve the underlying object through the Nullable.Value property.
Here's the sample code you need to create a nullable integer:
Dim i As Nullable(Of Integer) If Not i.HasValue Then ' This is true, because no value has been assigned. Console.WriteLine("i is a null value") End If ' Assign a value. Note that you must assign directly to i, not i.Value. ' The i.Value property is read-only, and it always reflects the ' currently assigned object, if it is not Nothing. i = 100 If i.HasValue Then ' This is true, because a value (100) is now present. Console.WriteLine("Nullable integer i = " & i.Value) End If
2.6.2. What about...
...using Nullable with full-fledged reference objects? Although you don't need this ability (because reference types can contain a null reference), it still gives you some advantages. Namely, you can use the slightly more readable HasValue() method instead of testing for Nothing. Best of all, you can make this change seamlessly, because the Nullable class has the remarkable ability to allow implicit conversions between Nullable and the type it wraps.
2.6.3. Where can I learn more?
To learn more about Nullable and how it's implemented, look up the "Nullable class" index entry in the MSDN Help.