Nullable types in C# are represented as <type>?, such
as int?. Any parameter or field type represented as int? supports a direct null
assignment. In addition, the nullable object definition adds two additional properties:
HasValue and Value. If you access the Value property when the value is null, an
exception is thrown, so where possible check the HasValue property first to
ensure the value is not null. Another option is to call the added method,
GetValueOrDefault().
Nullable types are represented by the generic class
Nullable<int>, and a new nullable object can be constructed with the
following long hand syntax.
Listing 4
new Nullable<int>(null);
new Nullable<int>(1);
Nullable values convert primitive types into reference
types, and this has to be handled specially. The previous situation will not
work in the same way. To determine if the type is nullable, use the following
line below. I have to thank Microsoft for this one; I stumbled across this as I
was examining the code for the JSON serialization process.
Listing 5
if (typeof(T).IsGenericType &&
typeof(T).GetGenericTypeDefinition() == typeof(Nullable<>))
The ideal situation is to use the Nullable type constructor,
but we need to extract the generic type and pass in a new nullable value. For
example, Nullable<int> is a reference type, but the generic argument
references a value type that can be useful in the code below.
Listing 6
Type parameterType = typeof(T).GetGenericArguments()[0];
Type nullableType = typeof(Nullable<>).MakeGenericType(parameterType);
return (T)Activator.CreateInstance(nullableType, new object[] {
Convert.ChangeType(value, parameterType) });
To create a new instance of the nullable type,
MakeGenericType takes the Nullable<> type and makes it
Nullable<int>. CreateInstance creates a new instance of the nullable
type, safely using Convert.ChangeType to convert the integer value.
To recap, because nullable types are not convertible, you
cannot simply say Convert.ChangeType(value, Nullable<int>) and expect this
to work. An exception will be thrown. To handle this, the GetGenericArguments
method extracts the "int" type. A nullable type is generated on the
fly and assigned to the nullableType field. Lastly, a new nullable type class
is constructed, passing in an integer.