Deborah's Developer MindScape






         Tips and Techniques for Web and .NET developers.

September 2, 2009

Nullable Data Types

Filed under: C#,VB.NET @ 4:12 pm

A data type is said to be nullable if it can be assigned a value or a null reference. Reference types, such as strings and class types, are nullable; they can be set to a null reference, and the result is a null value. Value types, such as integers, Booleans, and dates, are not nullable. If you set a value type to a null reference, the result is a default value, such as 0 or false.

Try this:

In C#:

int i  = null;
Boolean b  = null;
DateTime d = null;
Debug.WriteLine(i + ", " + b + ", " + d.ToShortDateString());

In VB:

Dim i As Integer = Nothing
Dim b As Boolean = Nothing
Dim d As DateTime = Nothing
Debug.WriteLine(i & ", " & b & ", " & d.ToShortDateString)

The C# code will generate compile-time errors saying you cannot convert null to the defined type because it is a non-nullable value type.

VB, however, will display this:

0, False, 1/1/0001

Instead of retaining a null value, VB sets the variable to the default value.

A value type can express only the values appropriate to its type; there is no easy way for a value type to understand that it is null.

There may be cases, however, when you need your code to really handle a null as a null and not as a default value. It would be odd, for example, to handle a null date by hard-coding a check for the 1/1/0001 date.

The .NET Framework 2.0 introduced a Nullable class and an associated Nullable structure. The Nullable structure includes the value type itself and a field identifying whether the value is null. A variable of a Nullable type can represent all the values of the underlying type, plus an additional null value. The Nullable structure supports only value types because reference types are nullable by design.

To make a value type property nullable, you need to declare it using the Nullable structure. However, you still want your property to be strongly typed as an integer, date, Boolean, or the appropriate underlying type. The ability to use a class or structure for only a specific type of data is the purpose of generics.

Generics allow you to tailor a class, structure, method, or interface to a specific data type. So you can create a class, structure, method, or interface with generalized code. When you use it, you define that it can work only on a particular data type. This gives you greater code reusability and type safety.

The .NET Framework built-in Nullable structure is generic. When you use the structure, you define the particular data type to use. As a specific example, an InventoryDate property that allows the date to be a date or a null value uses the generic Nullable structure as follows:

In C#:

public Nullable<DateTime> InventoryDate { get; set; }

In VB:

Private _InventoryDate As Nullable(Of DateTime)
Public Property InventoryDate() As Nullable(Of DateTime)
    Get
        Return _InventoryDate
    End Get
    Set(ByVal value As Nullable(Of DateTime))
        _InventoryDate = value
    End Set
End Property

Notice the syntax of the Nullable structure. Since it is a generic structure, it has the standard <T> [C#] or (Of T) [VB] syntax, where T is the specific data type you want it to accept. In this case, the Nullable structure supports dates, so the <DateTime> or (Of DateTime) syntax is used. This ensures that the Nullable structure contains only a date or a null value.

More commonly, however, the nullable structure is defined using the question mark (?) short-hand syntax:

In C#:

public DateTime? InventoryDate { get; set; }     

In VB:

Private _InventoryDate As DateTime?
Public Property InventoryDate() As DateTime?
    Get
        Return _InventoryDate
    End Get
    Set(ByVal value As DateTime?)
        _InventoryDate = value
    End Set
End Property

Both examples work the same way, but many developers prefer the shorter, question mark syntax.

You can then use this property in your application as needed. For
example:

In C#:

Product prod = new Product();
if (prod.InventoryDate.HasValue)
{
    if (prod.InventoryDate.Value < DateTime.Now.Date.AddDays(-10))
    {
        MessageBox.Show("Need to do an inventory");
    }
}
else
{
    MessageBox.Show("Need to do an inventory – never been done");
}

In VB:

Dim prod As New Product
If prod.InventoryDate.HasValue Then
    If prod.InventoryDate.Value < Now.Date.AddDays(-10) Then
        MessageBox.Show("Need to do an inventory")
    End If
Else
    MessageBox.Show("Need to do an inventory – never been done")
End If

The HasValue property of the Nullable class defines whether the value type has a value—in other words, whether it is null. If it does have a value, you can retrieve the value using the Value property of the Nullable class.

The Nullable structure is exceptionally useful when you’re working with databases, because empty fields in a database are often null. Assuming that you have an InventoryDate fi eld in a table, you could write code as follows:

In C#:

prod.InventoryDate =
    dt.Rows[0]["InventoryDate"] == DBNull.Value ?
               null : 
               (DateTime?)dt.Rows[0]["InventoryDate"];

In VB:

prod.InventoryDate = _
  
If(dt.Rows(0).Item("InventoryDate") Is DBNull.Value, _
               Nothing, _
               CType(dt.Rows(0)("InventoryDate"), DateTime))

The ternary operator is required here because you cannot convert a DBNull
to a date, so you need to ensure that it is not a null.

Use the Nullable structure any time you need to support nulls in a
value type, such as an integer, Boolean, or date.

(Based on an except from "Doing Objects in Visual Basic 2005".)

Enjoy!

2 Comments

  1.   Mark Wisecarver — September 2, 2009 @ 5:57 pm    Reply

    Awesome! Please don’t stop now. 😉
    All the best,
    Mark Wisecarver

  2.   Waleed El-Badry — September 4, 2009 @ 9:48 pm    Reply

    I remember studying the nullable types when I was preparing for the .NET Framework 2.0 exam as it was in the very beginning of the Microsoft self paced kit.

    The good thing is you used “ternary operator” which would do the job correctly.Developers may mix it up with “the immediate IF (IIF)” which would sometimes causes a logical bug that is hard to be found since many are not aware that it evaluates both true and false parts if they were functions.

    Thanks Deborah. You touched a vivid topic.

RSS feed for comments on this post. TrackBack URI

Leave a comment

© 2022 Deborah's Developer MindScape   Provided by WPMU DEV -The WordPress Experts   Hosted by Microsoft MVPs