How do I convert a System.Type to its nullable version?
Here is the code I use:
Type GetNullableType(Type type) {
// Use Nullable.GetUnderlyingType() to remove the Nullable<T> wrapper if type is already nullable.
type = Nullable.GetUnderlyingType(type) ?? type; // avoid type becoming null
if (type.IsValueType)
return typeof(Nullable<>).MakeGenericType(type);
else
return type;
}
I have a couple of methods I've written in my utility library that I've heavily relied on. The first is a method that converts any Type to its corresponding Nullable<Type> form:
/// <summary>
/// [ <c>public static Type GetNullableType(Type TypeToConvert)</c> ]
/// <para></para>
/// Convert any Type to its Nullable<T> form, if possible
/// </summary>
/// <param name="TypeToConvert">The Type to convert</param>
/// <returns>
/// The Nullable<T> converted from the original type, the original type if it was already nullable, or null
/// if either <paramref name="TypeToConvert"/> could not be converted or if it was null.
/// </returns>
/// <remarks>
/// To qualify to be converted to a nullable form, <paramref name="TypeToConvert"/> must contain a non-nullable value
/// type other than System.Void. Otherwise, this method will return a null.
/// </remarks>
/// <seealso cref="Nullable<T>"/>
public static Type GetNullableType(Type TypeToConvert)
{
// Abort if no type supplied
if (TypeToConvert == null)
return null;
// If the given type is already nullable, just return it
if (IsTypeNullable(TypeToConvert))
return TypeToConvert;
// If the type is a ValueType and is not System.Void, convert it to a Nullable<Type>
if (TypeToConvert.IsValueType && TypeToConvert != typeof(void))
return typeof(Nullable<>).MakeGenericType(TypeToConvert);
// Done - no conversion
return null;
}
The second method simply reports whether a given Type is nullable. This method is called by the first and is useful separately:
/// <summary>
/// [ <c>public static bool IsTypeNullable(Type TypeToTest)</c> ]
/// <para></para>
/// Reports whether a given Type is nullable (Nullable< Type >)
/// </summary>
/// <param name="TypeToTest">The Type to test</param>
/// <returns>
/// true = The given Type is a Nullable< Type >; false = The type is not nullable, or <paramref name="TypeToTest"/>
/// is null.
/// </returns>
/// <remarks>
/// This method tests <paramref name="TypeToTest"/> and reports whether it is nullable (i.e. whether it is either a
/// reference type or a form of the generic Nullable< T > type).
/// </remarks>
/// <seealso cref="GetNullableType"/>
public static bool IsTypeNullable(Type TypeToTest)
{
// Abort if no type supplied
if (TypeToTest == null)
return false;
// If this is not a value type, it is a reference type, so it is automatically nullable
// (NOTE: All forms of Nullable<T> are value types)
if (!TypeToTest.IsValueType)
return true;
// Report whether TypeToTest is a form of the Nullable<> type
return TypeToTest.IsGenericType && TypeToTest.GetGenericTypeDefinition() == typeof(Nullable<>);
}
The above IsTypeNullable implementation works like a champ every time, but it's slightly verbose and slow in its last code line. The following code body is the same as above for IsTypeNullable, except the last code line is simpler and faster:
// Abort if no type supplied
if (TypeToTest == null)
return false;
// If this is not a value type, it is a reference type, so it is automatically nullable
// (NOTE: All forms of Nullable<T> are value types)
if (!TypeToTest.IsValueType)
return true;
// Report whether an underlying Type exists (if it does, TypeToTest is a nullable Type)
return Nullable.GetUnderlyingType(TypeToTest) != null;
Enjoy!
Mark
P.S. - About "nullability"
I should repeat a statement about nullability I made in a separate post, which applies directly to properly addressing this topic. That is, I believe the focus of the discussion here should not be how to check to see if an object is a generic Nullable type, but rather whether one can assign a value of null to an object of its type. In other words, I think we should be determining whether an object type is nullable, not whether it is Nullable. The difference is in semantics, namely the practical reasons for determining nullability, which is usually all that matters.
In a system using objects with types possibly unknown until run-time (web services, remote calls, databases, feeds, etc.), a common requirement is to determine whether a null can be assigned to the object, or whether the object might contain a null. Performing such operations on non-nullable types will likely produce errors, usually exceptions, which are very expensive both in terms of performance and coding requirements. To take the highly-preferred approach of proactively avoiding such problems, it is necessary to determine whether an object of an arbitrary Type is capable of containing a null; i.e., whether it is generally 'nullable'.
In a very practical and typical sense, nullability in .NET terms does not at all necessarily imply that an object's Type is a form of Nullable. In many cases in fact, objects have reference types, can contain a null value, and thus are all nullable; none of these have a Nullable type. Therefore, for practical purposes in most scenarios, testing should be done for the general concept of nullability, vs. the implementation-dependent concept of Nullable. So we should not be hung up by focusing solely on the .NET Nullable type but rather incorporate our understanding of its requirements and behavior in the process of focusing on the general, practical concept of nullability.