Section 1.9. Express Null Values with Nullable Types


1.9. Express Null Values with Nullable Types

With new nullable types, you can assign value types a null value. This can be tremendously powerful, especially when working with databases where the value returned might be null; without nullable types you would have no way to express that an integer value is null, or that a Boolean is neither true nor false.


Note: With nullable types, a value type such as bool or int can have the value null.

1.9.1. How do I do that?

You can declare a nullable type as follows:

System.Nullable<T> variable

Or, if you are within the scope of a generic type or method, you can write:

T? variable

Thus, you can create two Nullable integer variables with these lines of code:

System.Nullable<int> myNullableInt; int? myOtherNullableInt;

You can check whether a nullable variable is null in two ways as well. You can check like this:

if (myNullableInt.HasValue)

or like this:

if (myNullableInt != null)

Each will return TRue if the myNullableInt variable is not null, and false if it is, as illustrated in Example 1-7.

Example 1-7. Nullable types
using System;     namespace NullableTypes {    public class Dog    {       private int age;       public Dog(int age)       {          this.age = age;       }    }           class Program    {       static void Main(string[  ] args)       {          int? myNullableInt = 25;          double? myNullableDouble = 3.14159;          bool? myNullableBool = null; // neither yes nor no              // string? myNullableString = "Hello"; // not permitted          // Dog? myNullableDog = new Dog(3);  // not permitted              if (myNullableInt.HasValue)          {             Console.WriteLine("myNullableInt is " + myNullableInt.Value);          }          else          {             Console.WriteLine("myNullableInt is undefined!");          }              if (myNullableDouble != null)          {             Console.WriteLine("myNullableDouble: " + myNullableDouble);          }          else          {             Console.WriteLine("myNullableDouble is undefined!");          }                    if ( myNullableBool != null )          {             Console.WriteLine("myNullableBool: " + myNullableBool);          }          else          {             Console.WriteLine("myNullableBool is undefined!");          }                  myNullableInt = null;      // assign null to the integer          // int a = myNullableInt; // won't compile              int b;          try          {             b = (int)myNullableInt;  // will throw an exception if x is null             Console.WriteLine("b: " + b);          }          catch (System.Exception e)          {             Console.WriteLine("Exception! " + e.Message);          }              int c = myNullableInt ?? -1;  // will assign -1 if x is null              Console.WriteLine("c: {0}", c);              // careful about your assumptions here          // If either type is null, all comparisons evaluate false!          if (myNullableInt >= c)          {             Console.WriteLine("myNullableInt is greater than or equal to c");          }          else          {             Console.WriteLine("Is myNullableInt less than c?");          }           }    } }

Output:

myNullableInt is 25 myNullableDouble: 3.14159 myNullableBool is undefined! Exception! Nullable object must have a value. c: -1 Is myNullableInt less than c?

1.9.2. What just happened?

Let's focus on the Main method. Five nullable types are created:

int? myNullableInt = 25; double? myNullableDouble = 3.14159; bool? myNullableBool = null; // neither yes nor no     // string? myNullableString = "Hello";  // Dog? myNullableDog = new Dog(3);

The first three are perfectly valid, but you cannot create a nullable string or a nullable user-defined type (class), and thus they should be commented out.


Note: However, structs can be user-defined, and it's OK to use them as nullables.

We check whether each nullable type is null (or, equivalently, whether the HasValue property is true). If so, we print their value (or equivalently, we access their Value property).

After this the value null is assigned to myNullableInt:

myNullableInt = null;

The next line would like to declare an integer and initialize it with the value in myNullableInt, but this is not legal; there is no implicit conversion from a nullable int to a normal int. You can solve this in two ways. The first is with a cast:

b = (int)myNullableInt;

This will compile, but it will throw an exception at runtime if myNullableInt is null (which is why we've enclosed it in a try/catch block).

The second way to assign a nullable int to an int is to provide a default value to be used in case the nullable int is null:

int c = myNullableInt ?? -1;

This line reads as follows: "initialize int c with the value in myNullableInt unless myNullableInt is null, in which case initialize c to -1."


Note: Comparison operators always return false if one value is null!

It turns out that all the comparison operators (>, <, <=, etc.) return false if either value is null. Thus, a true value can be trusted:

if (myNullableInt >= c) {    Console.WriteLine("myNullableInt is greater than or equal to c"); }


Warning: Note, however, that = = will return true if both arguments are null.

If the statement "myNullableInt is greater than or equal to c" displays, you know that myNullableInt is not null, nor is c, and that myNullableInt is greater than c. However, a false value cannot be trusted in the normal fashion:

else {    Console.WriteLine("Is myNullableInt less than c?"); }

This else clause can be reached if myNullableInt is less than c, but it can also be reached if either myNullableInt or c is null.

1.9.3. What about...

...Boolean null values? How are they compared to correspond to the SQL three-value Boolean type?

C# provides two new operators:

bool? operator &(bool? x, bool? y) bool? operator |(bool? x, bool? y)

You can use these operators to create the truth table depicted in Table 1-1.

Table 1-1. Truth table for nullable Boolean operators

If x is...

And y is...

x and y evaluate to...

x|y evaluates to...

True

True

True

True

True

False

False

True

True

Null

Null

True

False

True

False

True

False

False

False

False

False

Null

False

Null

Null

True

Null

True

Null

False

False

Null

Null

Null

Null

Null


1.9.4. Where can I learn more?

The Visual C# Developer Center has a good article on nullable types. Visit http://msdn.microsoft.com/vcsharp/2005/overview/language/nullabletypes/ for more information.



Visual C# 2005(c) A Developer's Notebook
Visual C# 2005: A Developers Notebook
ISBN: 059600799X
EAN: 2147483647
Year: 2006
Pages: 95
Authors: Jesse Liberty

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net