C# Generics Recipes—Creating a Value Type That Can be Initialized to Null
Microsoft .NET Framework, ASP.NET, Visual C# (CSharp, C Sharp, C-Sharp) Developer Training, Visual Studio
| CSharp-Online.NET:Articles |
| C# Articles |
| © 2006 O'Reilly Media, Inc. |
Contents |
4.7 Creating a Value Type That Can be Initialized to Null
Problem
You have a variable that is a numeric type, which will hold a numeric value obtained from a database. The database may return this value as a null. You need a simple clean way to store this numeric value, even if it is returned as a null.
Solution
Use a nullable value type. There are two ways of creating a nullable value type. The first way is to use the ? type modifier:
int? myDBInt = null;
The second way is to use the Nullable<T> generic type:
Nullable<int> myDBInt = new Nullable<int>( );
Discussion
Essentially both of the following statements are equivalent:
int? myDBInt = null; Nullable<int> myDBInt = new Nullable<int>( );
In both cases, myDBInt is considered a nullable type and is initialized to null. A nullable
type implements the INullableValue interface, which has two read-only property members, HasValue and Value. The HasValue property returns false if the nullable type is set to null; otherwise it returns true. If HasValue returns true, you can access the Value property, which contains the currently stored value in the nullable
data type. If HasValue returns false and you attempt to read the Value property, you will get an InvalidOperationException thrown. This is because the Value property is undefined at this point.
In addition, testing the nullable type can be done in one of two ways. First, by using the HasValue property as shown here:
if (myDBInt.HasValue) Console.WriteLine("Has a value: " + myDBInt.Value); else Console.WriteLine("Does not have a value (NULL)");
and, second, by comparing it to null:
if (myDBInt != null) Console.WriteLine("Has a value: " + myDBInt.Value); else Console.WriteLine("Does not have a value (NULL)");
Either method is acceptable.
When casting a nullable type to a non-nullable type, the cast operates as it would normally, except when the nullable type is set to null. In this case, an InvalidOperationException is thrown. When casting a non-nullable type to a nullable
type, the cast operates as it would normally. No InvalidOperationException will be
thrown, as the non-nullable type can never be null.
The tricky thing to watch out for with nullable types is when comparisons are performed. For example if the following code is executed:
if (myTempDBInt < 100) Console.WriteLine("myTempDBInt < 100"); else Console.WriteLine("myTempDBInt >= 100");
The text "myTempDBInt >= 100" is displayed, which is obviously incorrect. To fix
this code, you have to check if myTempDBInt is null. If it is not, you can execute the if
statement in the previous code block:
if (myTempDBInt != null) { if (myTempDBInt < 100) Console.WriteLine("myTempDBInt < 100"); else Console.WriteLine("myTempDBInt >= 100"); } else { // Handle the null here. } <CSO_Source> Another interesting thing about nullable types is that you can use them in expressions similar to normal numeric types, for example: <CSO_Source> int? DBInt = 10; int Value = 2; int? Result = DBInt + Value; // Result == 12
The result of using a nullable type in an expression is a null if any nullable type is
null. However, if none of the nullable types is null, the operation is evaluated as it
normally would be. If DBInt, for example, is set to null, the value placed in Result
will also be null.
See Also
See the "Nullable<T> Generic Class" and "Using Nullable Types" topics in the MSDN documentation.
|

