C# Reflection: How to get the type of a Nullable<int>?
Solution 1
Update: Looks like C# 7 will support switching on Type
s 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.
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, 2020Comments
-
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 over 12 yearsAre 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 over 12 yearsYou probably have to do this with
if
statements, rather than in aswitch
statement. But, like you, I've never done this before. It looks like an anti-pattern to me. -
DekluitTheNoob over 12 yearsVS 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 over 12 yearsinterestingly enough, when
int? a = 3
thentypeof( a)
is "System.Int32" -
Rick Sladkey over 12 years@Dr.Zim: See explanation here: stackoverflow.com/questions/785358/…
-
Zachary Scott over 12 yearsHad to use
myObject.GetType().GetProperty("ID").PropertyType == typeof( Nullable<Int64>)
in my special circumstance, but it worked. Thanks. -
CodesInChaos over 12 yearsJust like Eric said, there is no boxed
Nullable<T>
. Nullables get boxed as the underlying type if they are not null, ornull
which is typeless if they are. Thus your code won't work. -
CodesInChaos over 12 yearsThis structure exists. But
GetType()
will never returnNullable<T>
, sinceGetType()
operates on boxed values, and nullable values don't get boxed asNullable<T>
. So both the first and the thirdif
in your example will never be satisfied. -
CodesInChaos over 12 years@Dr.Zim
typeof(a)
doesn't even compile. It'sa.GetType()
that returnsint
. -
CodesInChaos over 12 yearsHe worked on
myObject.GetType().GetProperty("ID").PropertyType
. The static type of the property can beNullable<T>
, it's justGetType()
that can't return a nullable. -
nawfal almost 8 yearsWrong answer.
myObject.GetType
will always giveint
if it is declared either asint
orint?
-
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 over 6 yearsAgree with @CodesInChaos & @nawfal. Answer is misleading.
GetType()
operates on a boxed value. docs.microsoft.com/en-us/dotnet/csharp/programming-guide/… -
Sam Rueby over 6 yearsUpdate: in C# 7, switch statements no-longer require constant expressions :)
-
Eric Lippert over 6 yearsAnd provide a mechanism for switching on types. That feature was first proposed in... 2001? I think. So, 16 years, not bad.
-
M.Babcock over 6 yearsCorrected answer several years too late to help the asker, but people keep coming here so hopefully it'll help someone else.
-
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 toReadOnlySpan<char>
=/