tags:

views:

3653

answers:

4

Hi,

How do I check if a given object is nullable in other words how to implement the following method...

bool IsNullableValueType(object o)
{
    ...
}

EDIT: I am looking for nullable value types. I didn't have ref types in mind.

//Note: This is just a sample. The code has been simplified 
//to fit in a post.

public class BoolContainer
{
 bool? myBool = true;
}

var bc = new BoolContainer();

const BindingFlags bindingFlags = BindingFlags.Public
      | BindingFlags.NonPublic
      | BindingFlags.Instance
      ;


object obj;
object o = (object)bc;

foreach (var fieldInfo in o.GetType().GetFields(bindingFlags))
{
 obj = (object)fieldInfo.GetValue(o);
}

obj now refers to an object of type bool (System.Boolean) with value equal to true. What I really wanted was an object of type Nullable<bool>

So now as a work around I decided to check if o is nullable and create a nullable wrapper around obj.

+20  A: 

There are two types of nullable - Nullable<T> and reference-type.

Jon has corrected me that it is hard to get type if boxed, but you can with generics: - so how about below. This is actually testing type T, but using the obj parameter purely for generic type inference (to make it easy to call) - it would work almost identically without the obj param, though.

    static bool IsNullable<T>(T obj)
    {
        if (obj == null) return true; // obvious
        Type type = typeof(T);
        if (!type.IsValueType) return true; // ref-type
        if (Nullable.GetUnderlyingType(type) != null) return true; // Nullable<T>
        return false; // value-type
    }

But this won't work so well if you have already boxed the value to an object variable.

Marc Gravell
The last line is only valid if you somehow manage to get a boxed Nullable<T> instead of boxing straight to T. It's possible, but tricky to achieve from what I remember.
Jon Skeet
Ah, you're right...
Marc Gravell
Thanks `Nullable.GetUnderlyingType(type) != null` is what I was looking for.
SDX2000
+6  A: 

Well, you could use:

return !(o is ValueType);

... but an object itself isn't nullable or otherwise - a type is. How were you planning on using this?

Jon Skeet
This threw me off a bit. e.g. int? i = 5; typeof(i) returns System.Int32 instead of Nullable<Int32> -- typeof(int?) returns Nullable<Int32>.. where can I get some clarity on this topic?
Gishu
typeof(i) will give a compiler error- you can't use typeof with a variable. What did you actually do?
Jon Skeet
:) As i said.. i am all shook up. I did i.GetType()
Gishu
i.GetType() will box to Object first, and there's no such thing as a boxed nullable type - Nullable<int> gets boxed to a null reference or a boxed int.
Jon Skeet
thanks.. got the missing piece.
Gishu
+2  A: 

Be carefull, when boxing a nullable type (Nullable<int> or int? for instance) :

int? nullValue = null;
object boxedNullValue = (object)nullValue;
Debug.Assert(boxedNullValue == null);

int? value = 10;
object boxedValue = (object)value;
Debug.Assert( boxedValue.GetType() == typeof(int))

It becomes a true reference type, so you lose the fact it was nullable.

Think Before Coding
A: 
bool IsNullableValueType(object o)
{
    Type objType = o.GetType();

    if (objType.FullName.StartsWith(typeof(Nullable<>).FullName))
    {
        return Nullable.GetUnderlyingType(objType).IsValueType;
    }

    return false;
}
Drakiula
objType.FullName.StartsWith(typeof(Nullable<>).FullName)...What purpose does this serve?
SDX2000
To check if objTyoe is nullable.
Drakiula
Thx for voting against, btw, anyone bothered to compile this code?What is wrong with it?
Drakiula
Nullable.GetUnderlyingType(objType) returns null if objType is not nullable there is no need to resort to string comparisons for this. Have you read/understood the accepted answer?
SDX2000
Nullable.GetUnderlyingType(objType) is not getting called if the object is not nullable, so ...Did you check the if condition?Nevermind.
Drakiula