smartcaveman
smartcaveman

Reputation: 42246

How to determine if a non-null object is a Nullable struct?

Is there anyway to know this?

I found one post that asked a very similar question at How to check if an object is nullable? The answer explains how to determine if an object is nullable if there is access to a Generic Type Parameter. This is accomplished by using Nullabe.GetUnderlyingType(typeof(T)). However, if you only have an object and it is not null, can you determine if it is actually a Nullable ValueType?

In other words, is there a better way than checking every possible nullable value type individually to determine if a boxed struct is a value type?

void Main(){
    Console.WriteLine(Code.IsNullableStruct(Code.BoxedNullable));
} 


public static class Code{
    private static readonly int? _nullableInteger = 43;

    public static bool IsNullableStruct(object obj){
                  if(obj == null) throw new ArgumentNullException("obj");
                  if(!obj.GetType().IsValueType) return false;
                  return IsNullablePrimitive(obj);
            }
    public static bool IsNullablePrimitive(object obj){
         return obj is byte? || obj is sbyte? || obj is short? || obj is ushort? || obj is int? || obj is uint? || obj is long? || obj is ulong? || obj is float? || obj is double? || obj is char? || obj is decimal? || obj is bool? || obj is DateTime? || obj is TimeSpan?;
    }

    public static object BoxedNullable{
        get{ return _nullableInteger; }
    }
}

-

Update

I found this article at MSDN, and it says you can't determine if a type is a Nullable struct via a call to GetType().

-

Update #2

Apparently the method I suggested doesn't work either because int x = 4; Console.WriteLine(x is int?); is True. (See the comment)

Upvotes: 5

Views: 587

Answers (4)

Scott
Scott

Reputation: 1876

Nullable<> is a special class. When you try to inspect or copy a Nullable<> it is converted/boxed to either 'null' or the value type it contains. Calling GetType() would actually throw an exception if your Nullable<> doesn't have a value, or at best return the underlying type. The spoofing occurs at the lowest level. You cannot identify a Nullable<> through any kosher means.

Upvotes: 0

Cory Nelson
Cory Nelson

Reputation: 30001

When you box a nullable, it actually boxes its underlying type. Nullable<int> will turn into a boxed int. There is no way to tell if the source of an boxed value type was a Nullable.

Note that your IsNullablePrimitive will actually return true if you pass it a non-Nullable int!

Upvotes: 1

Rick Sladkey
Rick Sladkey

Reputation: 34250

Quoting Jon Skeet's comment in the question you linked:

there's no such thing as a boxed nullable type - Nullable gets boxed to a null reference or a boxed int

so in your example program by the time BoxedNullable is passed to IsNullableStruct which takes an object as a parameter, the value is already a boxed 43, no longer a nullable anything. Ironically x is int? is true for any int, nullable or otherwise, so that only adds to the confusion.

In any case, your original question, according to Jon's comment, doesn't seem to make sense.

Upvotes: 4

Tejs
Tejs

Reputation: 41246

Yes, you simply check the generic definition:

protected bool IsNullableType(Type type)
{
    if(!type.IsGeneric)
        return false;

    return type.GetGenericDefinition() == typeof(Nullable<>);
}

Effectively, these statements are the same:

var type = typeof(Nullable<>);
var type2 = new Nullable<int>().GetType().GetGenericDefinition();

Upvotes: -1

Related Questions