5

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)

Community
  • 1
  • 1
smartcaveman
  • 41,281
  • 29
  • 127
  • 212

4 Answers4

4

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.

Rick Sladkey
  • 33,988
  • 6
  • 71
  • 95
  • 1
    [Here is the article on MSDN which explains this](http://msdn.microsoft.com/en-us/library/ms228597.aspx). – porges May 12 '11 at 04:01
1

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!

Cory Nelson
  • 29,236
  • 5
  • 72
  • 110
0

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.

Scott
  • 1,876
  • 17
  • 13
-1

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();
Tejs
  • 40,736
  • 10
  • 68
  • 86
  • (1) Your syntax is wrong. (2) Assuming you intended the equivalent to `return !type.IsGenericType ? false : type.GetGenericTypeDefinition() == typeof(Nullable<>);`, your answer is still incorrect. The two statements are not equivalent, try it out – smartcaveman May 12 '11 at 03:29
  • 2
    Those statements are _not_ the same. Nullable.GetType() actually returns T. – Cory Nelson May 12 '11 at 03:30
  • Interesting. I learn something new every day! I would have expected it to work like almost every other generic out there. – Tejs May 12 '11 at 03:39