C# Reflection: How to get the type of a Nullable<int>?

29,878

Solution 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

Solution 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.

Solution 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?

Solution 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.

Share:
29,878
Zachary Scott
Author by

Zachary Scott

#SOreadytohelp Recommended books: Agile Principles, Patterns, and Practices in C# Applying Domain-Driven Design and Patterns Patterns of Enterprise Application Architecture Design Patterns (GOF) Refactoring: Improving the Design of Existing Code Test Driven Development: By Example Implementation Patterns Domain-Driven Design (Evans)

Updated on November 11, 2020

Comments

  • Zachary Scott
    Zachary Scott over 3 years

    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.

  • Zachary Scott
    Zachary Scott over 12 years
    Are you sure you compare .GetType() to typeof( Nullable<Int32>) or is it a property under GetType()? Assuming int? and Nullable<Int32> are the same type, a.GetType() != typeof( Nullable<Int32>).
  • Cody Gray
    Cody Gray over 12 years
    You probably have to do this with if statements, rather than in a switch statement. But, like you, I've never done this before. It looks like an anti-pattern to me.
  • DekluitTheNoob
    DekluitTheNoob over 12 years
    VS studio will have panic attack over the above code switch(myObject.GetType()) will show an IDE error of "Value of integral type expected" and case typeof(XXX) will show an IDE error of "Constant Value is expected"
  • Zachary Scott
    Zachary Scott over 12 years
    interestingly enough, when int? a = 3 then typeof( a) is "System.Int32"
  • Rick Sladkey
    Rick Sladkey over 12 years
    @Dr.Zim: See explanation here: stackoverflow.com/questions/785358/…
  • Zachary Scott
    Zachary Scott over 12 years
    Had to use myObject.GetType().GetProperty("ID").PropertyType == typeof( Nullable<Int64>) in my special circumstance, but it worked. Thanks.
  • CodesInChaos
    CodesInChaos over 12 years
    Just like Eric said, there is no boxed Nullable<T>. Nullables get boxed as the underlying type if they are not null, or null which is typeless if they are. Thus your code won't work.
  • CodesInChaos
    CodesInChaos over 12 years
    This structure exists. But GetType() will never return Nullable<T>, since GetType() operates on boxed values, and nullable values don't get boxed as Nullable<T>. So both the first and the third if in your example will never be satisfied.
  • CodesInChaos
    CodesInChaos over 12 years
    @Dr.Zim typeof(a) doesn't even compile. It's a.GetType() that returns int.
  • CodesInChaos
    CodesInChaos over 12 years
    He worked on myObject.GetType().GetProperty("ID").PropertyType. The static type of the property can be Nullable<T>, it's just GetType() that can't return a nullable.
  • nawfal
    nawfal almost 8 years
    Wrong answer. myObject.GetType will always give int if it is declared either as int or int?
  • Connell
    Connell over 7 years
    +1 and worth noting this method does the same check inside and returns null if the given type is not typeof(Nullable<>) so doing a null check afterwards instead of the if statement would also work.
  • Sam Rueby
    Sam Rueby over 6 years
    Agree with @CodesInChaos & @nawfal. Answer is misleading. GetType() operates on a boxed value. docs.microsoft.com/en-us/dotnet/csharp/programming-guide/…
  • Sam Rueby
    Sam Rueby over 6 years
    Update: in C# 7, switch statements no-longer require constant expressions :)
  • Eric Lippert
    Eric Lippert over 6 years
    And provide a mechanism for switching on types. That feature was first proposed in... 2001? I think. So, 16 years, not bad.
  • M.Babcock
    M.Babcock over 6 years
    Corrected answer several years too late to help the asker, but people keep coming here so hopefully it'll help someone else.
  • StingyJack
    StingyJack about 3 years
    "types are not constants" I would have thought that types would be constant since they are kind of hard to change during runtime (sans DLR). This probably explains (or justifies/is justified by) all of the string types being changed to ReadOnlySpan<char> =/