Nathan Ridley Nathan Ridley - 3 months ago 8
C# Question

How do I tell if a type is a "simple" type? i.e. holds a single value

typeof(string).IsPrimitive == false
typeof(int).IsPrimitive == true
typeof(MyClass).IsClass == true
typeof(string).IsClass == true
typeof(string).IsByRef == false
typeof(MyClass).IsByRef == true // correction: should be false (see comments below)


I have a method that instantiates a new instance of T and, if it's a "complex" class, fills its properties from a set of source data values.

(a) If T is a simple type (e.g. a string or an int or anything else similar), a quick conversion from the source data to T is to be performed.

(b) If T is a class (but not something simple like string), then I'll use Activator.CreateInstance and do a bit of reflection to populate the fields.

Is there a quick and simple way to tell if I should use method (a) or method (b)? This logic will be used inside a generic method with T as the type argument.

Answer

String is probably a special case.

I think I would do.....

bool IsSimple(Type type)
{
    return type.IsPrimitive 
      || type.Equals(typeof(string)));
}

Edit:

Sometimes you need to cover some more cases, like enums and decimals. Enums are a special kind of type in C#. Decimals are structs like any other. The problem with the structs is that they may be complex, they may be user defined types, they may be just a number. So you don't have any other chance than knowing them to differentiate.

bool IsSimple(Type type)
{
  return type.IsPrimitive 
    || type.IsEnum
    || type.Equals(typeof(string))
    || type.Equals(typeof(decimal));
}

Handling nullable counterparts are also a bit tricky. The nullable itself is a struct.

bool IsSimple(Type type)
{
  if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(Nullable<>))
  {
    // nullable type, check if the nested type is simple.
    return IsSimple(type.GetGenericArguments()[0]);
  }
  return type.IsPrimitive 
    || type.IsEnum
    || type.Equals(typeof(string))
    || type.Equals(typeof(decimal));
}

Test:

Assert.IsTrue(IsSimple(typeof(string));
Assert.IsTrue(IsSimple(typeof(int));
Assert.IsTrue(IsSimple(typeof(decimal));
Assert.IsTrue(IsSimple(typeof(float));
Assert.IsTrue(IsSimple(typeof(StringComparison));  // enum
Assert.IsTrue(IsSimple(typeof(int?));
Assert.IsTrue(IsSimple(typeof(decimal?));
Assert.IsTrue(IsSimple(typeof(StringComparison?));
Assert.IsFalse(IsSimple(typeof(object));
Assert.IsFalse(IsSimple(typeof(Point));  // struct
Assert.IsFalse(IsSimple(typeof(Point?));
Assert.IsFalse(IsSimple(typeof(StringBuilder)); // reference type
Comments