C# Reflection: How to get the type of a Nullable

2020-02-26 14:23发布

问题:

What I want to do is something like this:

switch( myObject.GetType().GetProperty( "id") )
{
    case ??: 
        // when Nullable<Int32>, do this
    case ??:
        // when string, do this
    case ??:
        // when Nullable<bool>, do this

What path under object.GetType() would have the string name of the datatype that I could compare using a case statement? I need to know the type so I can have one of many Convert.ToInt32( string ) that will set the value of myObject using Reflection.

回答1:

Update: Looks like C# 7 will support switching on Types as the asker of this question was trying to do. It's a little different though so watch out for syntax landmines.

You don't need a string name to compare it:

if (myObject.GetType().GetProperty("id").PropertyType == typeof(Nullable<Int32>))
    // when Nullable<Int32>, do this
else if (myObject.GetType().GetProperty("id").PropertyType == typeof(string))
    // when string, do this
else if (myObject.GetType().GetProperty("id").PropertyType == typeof(Nullable<bool>))
    // when Nullable<bool>, do this


回答2:

I've been using the following type of code to check if the type is nullable and to get the actual type:

if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
{
    return Nullable.GetUnderlyingType(type);
}

If the type is e.g. Nullable this code returns the int part (underlying type). If you just need to convert object into specific type you could use System.Convert.ChangeType method.



回答3:

The question is very confusing. Is "myObject" the object that might be a nullable int? Or is the property "id" possibly of type nullable int?

If the former, your question cannot be answered because it presupposes a falsehood. There is no such thing as a boxed nullable int. I note that all of the answers which propose if (myobject.GetType() == typeof(int?)) are therefore incorrect; the condition will never be true.

When you convert a nullable int to object, either it becomes a null reference (if the nullable int had no value) or it becomes a boxed int. There is no way to determine if an object contains a nullable int because an object never contains a nullable int.

If the latter, compare the property type to typeof(int?). You cannot use a switch; only constants may be used for switch cases and types are not constants.

All that said, this is a bad code smell. Why are you using reflection in the first place?



回答4:

In .net, instances of value types are just collections of bits, with no associated type information. For every value type other than Nullable<T>, however, the system also auto-generates a corresponding class type which derives from System.ValueType. A widening conversion exists from the value type to the auto-generated class type, and a narrowing conversion from the auto-generated class type to the value type. In the case of Nullable<T>, there is no corresponding auto-generated class type with conversions to/from the value type; instead, widening conversions exist in both directions between Nullable<T> and the class type associated with T.

As far as I can tell, this weird behavior was implemented to allow comparisons between null and an empty Nullable<T> to return true.



回答5:

As @Cody Gray said if statements would probably be the best way

var t = myObject.GetType();

if (t == typeof(Nullable<int>))
{ }
else if (t == typeof(string))
{}
else if (t==typeof(Nullable<bool>))
{}