16

I want to check if a Type is primitive or not and used the following code:

return type.IsValueType && type.IsPrimitive;

This works fine aslong as the primitive isnt nullable. For example int?, how can I check if the type is a nullable primitive type? (FYI: type.IsPrimitive == false on int?)

Rand Random
  • 7,300
  • 10
  • 40
  • 88
  • 1
    You need to identify nullable types and then drill into them to get the closed generic type out: http://stackoverflow.com/questions/5644587/find-type-of-nullable-properties-via-reflection `Nullable` isn't primitive, it's just a `struct` wrapper around other `struct` types with extra compiler support. – Adam Houldsworth Jan 07 '14 at 14:18
  • 1
    That `int?` is a shorthand for `Nullable`, so it is correct that it is not reported as primitive. – Hans Kesting Jan 07 '14 at 14:19
  • Nullables use the Generic type, which is not primitive by definition. Try the bellow suggestions :) – safejrz Jan 07 '14 at 14:21
  • What are you actually trying to achieve? I'm asking because often there are better approaches than using reflection. – Tim Schmelter Jan 07 '14 at 14:25
  • @TimSchmelter I am doing a deep clone and using the following (http://stackoverflow.com/a/11308879/2598770) but I want to modify it a bit and noticed that the check of IsPrimitive doesnt care about nullable ints. – Rand Random Jan 07 '14 at 14:29

3 Answers3

18

From MSDN:

The primitive types are Boolean, Byte, SByte, Int16, UInt16, Int32, UInt32, Int64, UInt64, IntPtr, UIntPtr, Char, Double, and Single.

So basically you should expect Nullable<Int32> to not be a primitive type.

You could use Nullable.GetUnderlyingType to "extract" Int32 from Nullable<Int32>.

ken2k
  • 48,145
  • 10
  • 116
  • 176
  • Thx for the Nullable.GetUnderlyingType, you dont happen to know a way to check a custom collection if its type.IsArray and than cast it to array if it is? For example: CustomList : IList, IList, IEnumerable – Rand Random Jan 07 '14 at 15:13
  • 1
    @RandRandom: This is a question-and-answer site; if that's your question then *post it as a question*, not as a comment. – Eric Lippert Jan 07 '14 at 15:47
13

First you'll need to determine if it's Nullable<> and then you'll need to grab the nullable types:

if (type.IsGenericType
    && type.GetGenericTypeDefinition() == typeof(Nullable<>)
    && type.GetGenericArguments().Any(t => t.IsValueType && t.IsPrimitive))
{
    // it's a nullable primitive
}

Now, the aforementioned works, but not recursively. To get it to work recursively you'll need to put this into a method that you can call recursively for all types in GetGenericArguments. However, don't do that if it's not necessary.

That code may also be able to be converted to this:

if (type.GetGenericArguments().Any(t => t.IsValueType && t.IsPrimitive))
{
    // it's a nullable primitive
}

but the caveat there is that it may be a generic reference type and may not actually meet the definition of primitive for your needs. Again, remember, the aforementioned is more concise but could return a false positive.

Mike Perrenoud
  • 66,820
  • 29
  • 157
  • 232
2

The reason IsPrimitive fails on Nullable<int> (also known as int?) is that Nullable<int> is not a primitive. It is an instance of a generic class Nullable<T> with the type parameter of int.

You can check if a number is a nullable primitive by verifying that

  • It is a generic type,
  • Its generic type definition is Nullable<>, and
  • Its generic parameter type IsPrimitive.
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523