How do I convert a System.Type to its nullable version?

Viewed 26298

Once again one of those: "Is there an easier built-in way of doing things instead of my helper method?"

So it's easy to get the underlying type from a nullable type, but how do I get the nullable version of a .NET type?

So I have

typeof(int)
typeof(DateTime)
System.Type t = something;

and I want

int? 
DateTime?

or

Nullable<int> (which is the same)
if (t is primitive) then Nullable<T> else just T

Is there a built-in method?

4 Answers

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;
}

Lyman's answer is great and has helped me, however, there's one more bug which needs to be fixed.

Nullable.GetUnderlyingType(type) should only be called iff the type isn't already a Nullable type. Otherwise, it seems to erroneously return null when the type derives from System.RuntimeType (such as when I pass in typeof(System.Int32) ). The below version avoids needing to call Nullable.GetUnderlyingType(type) by checking if the type is Nullable instead.

Below you'll find an ExtensionMethod version of this method which will immediately return the type unless it's a ValueType that's not already Nullable.

Type NullableVersion(this Type sourceType)
{
    if(sourceType == null)
    {
        // Throw System.ArgumentNullException or return null, your preference
    }
    else if(sourceType == typeof(void))
    { // Special Handling - known cases where Exceptions would be thrown
        return null; // There is no Nullable version of void
    }

    return !sourceType.IsValueType
            || (sourceType.IsGenericType
               && sourceType.GetGenericTypeDefinition() == typeof(Nullable<>) )
        ? sourceType
        : typeof(Nullable<>).MakeGenericType(sourceType);
}

(I'm sorry, but I couldn't simply post a comment to Lyman's answer because I was new and didn't have enough rep yet.)

There isn't anything built in that I know of, as the int?, etc. is just syntactic sugar for Nullable<T>; and isn't given special treatment beyond that. It's especially unlikely given you're attempting to obtain this from the type information of a given type. Typically that always necessitates some 'roll your own' code as a given. You would have to use Reflection to create a new Nullable type with type parameter of the input type.

Edit: As the comments suggest actually Nullable<> is treated specially, and in the runtime to boot as explained in this article.

Related