Wrapping up Nullable<T>

Even though I’ve thought that the previous posts were enough for presenting the Nullable<T> type, the truth is that I’ve received a question about them from a friend of mine. Here’s what he was asking:

If GetType returns T’s type, then how do you know you’re working with a nullable value type?

Nice question…glad you’ve asked about it, though I was saving that part for a future post about reflection. Anyway, the question was asked and I thought I’d give a quick answer here. As we’ve seen in previous posts, Nullable<T> instances have special support and that means that getting the “real” underlying type isn’t really that easy. In practice, we want to ensure this behavior:

Int32? aux = 5;
Console.WriteLine(IsNullable( aux ));//true
Console.WriteLine(IsNullable( 10 ));//false

Our IsNullable helper method can only return true when it receives a Nullable<T> instance. If, like me, some of your day time is used reading the framework’s code in Reflector, then you’ll probably noticed that there’s a Nullable helper class which exposes several utility methods. One of them is of special interest to us. I’m talking about the GetUnderlyingType method, whose implementation looks like this:

public static Type GetUnderlyingType( Type nullableType ) {
    if( nullableType == null ) {
        throw new ArgumentNullException( "nullableType" );
    }
    Type type = null;
    if( ( nullableType.IsGenericType && !nullableType.IsGenericTypeDefinition ) &&
        ( nullableType.GetGenericTypeDefinition( ) == typeof( Nullable<> ) ) ) {
        type = nullableType.GetGenericArguments( )[0];
    }
    return type;
}

As you can see, the method will return null when it doesn’t receive a Nullable<T> type. It’s also obvious that the method relies heavily in the Type class, which  offers several interesting members that allows us to see if we’re working with a Nullable<T> instance. With this information, it’s time to try to build the first  version of our IsNullable helper method:

private static Boolean IsNullable( Type value ) {
    return Nullable.GetUnderlyingType( value ) != null;
}

hum…you know what? This won’t really work…why? it’s simple: if we write IsNullable(aux.GetType()), we’ll end up with something like IsNullable(typeof(Int32)) and that will always return false. What about changing the declaration of IsNullable so that value is an object reference?

private static Boolean IsNullable( Object value ) {
    return Nullable.GetUnderlyingType( value.GetType(  ) ) != null;
}

Nop, that won’t work either because the Nullablet<T> GetType “special” method will still produce the wrong results. Going back to the first version of IsNullable, you can see that if we call it like this:

IsNullable( typeof(Int32?) )

It produces the expected result. So, what we need is a way to infer the type of a variable without specifying explicitly through the GetType call. Is there a way to solve this problem? Yes, there is: enter generic type inference! Here’s our final version of the IsNullable method:

private static Boolean IsNullable<T>( T value ) {
    return Nullable.GetUnderlyingType( typeof( T ) ) != null;
}

And now, we can call the method by passing it a value:

Int32? aux = 5;
Console.WriteLine( IsNullable( aux) ); //true
Console.WriteLine( IsNullable( 10 ) ); //false

As you can see, IsNullable relies on the typeof operator for producing the correct result. Another interesting thing is that the IsNullable method doesn’t really use the value var for anything: it’s only there so that the compiler can infer its type. And there you go: a nice trick for checking if a variable is a nullable value type. Before ending, it’s important to give credit to the guy that presented this strategy. I’m talking about Jon Skeet, who presented this code while answering a similar question on the stackoverflow site. And that’s it for now. Stay tuned for more.

Advertisements

~ by Luis Abreu on June 6, 2011.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

 
%d bloggers like this: