Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Detecting a Nullable Type via reflection

Surprisingly the following code fails the Assert:

int? wtf = 0;
Assert.IsType<Nullable<int>>(wtf);

So just out curiosity, how can you determine if a given instance is a Nullable<> object or not?

like image 378
justin.m.chase Avatar asked May 17 '11 05:05

justin.m.chase


People also ask

How are nullable types declared in C#?

You can declare nullable types using Nullable<t> where T is a type. Nullable<int> i = null; A nullable type can represent the correct range of values for its underlying value type, plus an additional null value. For example, Nullable<int> can be assigned any value from -2147483648 to 2147483647, or a null value.

Is nullable datetime a reference type?

Nullable types represent value-type variables that can be assigned the value of null. You cannot create a nullable type based on a reference type. (Reference types already support the null value.) So, no they're not reference types.

What happens when we box or unbox nullable types?

Boxing a value of a nullable-type produces a null reference if it is the null value (HasValue is false), or the result of unwrapping and boxing the underlying value otherwise. will output the string “Box contains an int” on the console.


3 Answers

Well firstly, Nullable<T> is a struct, so there isn't an object as such. You can't call GetType(), as that will box the value (at which point you either get null and thus an exception, or a boxed non-nullable value and therefore not the type you want).

(Boxing is what's messing up your assertion here - I would assume that IsType accepts object.)

You can use type inference though to get the type of the variable as a type parameter:

public bool IsNullable<T>(T value)
{
    return Nullable.GetUnderlyingType(typeof(T)) != null;
}

That's not a huge amount of use when you know the exact type at compile-time as in your example, but it's useful for generics. (There are alternative ways of implementing it, of course.)

What's your real life situation? I assume it's not an assertion like this, given that you know the answer to this one at compile time.

like image 144
Jon Skeet Avatar answered Oct 16 '22 11:10

Jon Skeet


I like the @jon-skeet answer but it only works if you know the type you are testing against. In our world we are using reflection to open up objects and test values against regex expressions.

simplifying the extension to work for any type worked better for us.

public static bool IsNullable(this Type type)
{
    return Nullable.GetUnderlyingType(type) != null;
}

generics are life's blood but sometimes... :)

like image 44
hal9000 Avatar answered Oct 16 '22 11:10

hal9000


int? i = 0;
var type = TypedReference.GetTargetType(__makeref(i));
var isNullable = type.IsGenericType &&
    type.GetGenericTypeDefinition() == typeof(Nullable<>);
like image 4
Vladimir Avatar answered Oct 16 '22 11:10

Vladimir