System.Nullable: Enabling value types to take a NULL value
What is it?
System.Nullable provides a means for value types to take a null value. For example a nullable boolean can have one of three states: null, false and true.
Which C# version supports it?
Version 2.0 and above.
Why would you use it?
Databases use null as being distinct from values such as 0 and false. Without nullable types, an arbitrary decision on how to represent null must be taken. Is a null in a boolean field equivalent to false? Only if you choose it to be. In many situations it may be equally valid to map it to true. Nullable types overcome this problem and allow any database value - including the “no value” of null - to be mapped directly to value types in C#.
Databases are not the only example either. Any situation where something may not be defined, and only has a meaningful value if it is defined, benefits from nullable types. Think of optional parameters in XML or HTML for example; likewise with the square root of -1 in real number scenarios; the age of a customer who declined to say how old they are; or the time to completion of some batch process that’s not yet started.
How to use it
The System.Nullable<T> struct
The bulk of the nullable type functionality is provided via the System.Nullable
Example 1: null is not the same as 0
The first example demonstrates declaring System.Nullable variables and comparing them.
System.Nullable<int> i1 = 0;
System.Nullable<int> i2 = null;
int i3 = 0;
if (i1 == i2)
{
System.Console.WriteLine("i1 and i2 are the same");
}
else
{
System.Console.WriteLine("i1 and i2 are different");
}
if (i1 == i3)
{
System.Console.WriteLine("i1 and i3 are the same");
}
else
{
System.Console.WriteLine("i1 and i3 are different");
}
i1 and i2 are different
i1 and i3 are the same
Beyond the obvious - that 0 and null are not the same - there are two handy features revealed by this code. It is possible to directly compare nullable values with their underlying value type without having to cast, or explicitly extract that underlying value. Likewise a nullable type can be directly assigned a value, rather than needing to cast the value into the nullable type.
Example 2: Accessing a nullable type’s value
The second example demonstrates that the value of a nullable type can only be read if it is not null.
System.Nullable<int> i1 = null;
try
{
System.Console.WriteLine("The value is {0}", i1.Value);
}
catch
{
System.Console.WriteLine("null causes an exception");
}
i1 = 1;
try
{
System.Console.WriteLine("The value is {0}", i1.Value);
}
catch
{
System.Console.WriteLine("1 causes an exception");
}
The output this time is:
null causes an exception
The value is 1
The actual exception thrown when System.Nullable<T>.Value is called is the System.InvalidOperationException.
The System.Nullable class
The method is the class (static) method System.Nullable.GetUnderlyingType(). The obvious (and I must admit only) use I’m aware of for this method is when using reflection. To demonstrate this, consider the following two lines of code:
System.Nullable<int> i1 = 1;
System.Console.WriteLine("i1 is type {0}", i1.GetType());
This gives the following output:
i1 is type System.Int32
Thus unless you are reflecting over methods and their return types, there is no obvious need for the System.Nullable.GetUnderlyingType() method. Reflection is beyond the scope of this article, so I’ll cover this feature no further here.
The Syntactic Sugar
C# defines two handy short-hand ways of using nullable types.
1. Declaring a nullable type
C# supports a short-hand way of declaring a variable of a nullable type. So the two following lines are functionally identical:
System.Nullable<int> v = null; int? v = null;
The general form is that T? is identical to System.Nullable<T>.
2. Assigning a value to a nullable variable only if it is null
A further C# short-hand feature means that the following have the same functionality too:
int DefaultIfNull(System.Nullable<int> i)
{
int retVal;
if (i.HasValue)
{
retVal = i;
}
else
{
retVal = 1;
}
return retVal;
}
int DefaultIfNull(System.Nullable<int> i)
{
return i ?? 10;
}
The first version of the method checks whether the parameter - i - has a value. If it does then it returns that value. If it has no value, ie is null, then it returns 10. The second function does exactly the same, it just uses the ?? notation to express that functionality. This function takes the general form:
T returnValue = System.Nullable<T> parameter ?? T default value;
In other words the ?? function will return a value of type T. If the parameter is not null, then it returns the value of the parameter, otherwise is returns the default value. It is important to note that the return value is not a nullable type; it is a value type.
No comments yet. Be the first.
Leave a reply
