如何判断类型是否为“简单”类型?即持有单一价值

时间:2009-05-14 15:06:22

标签: c# .net generics

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)

我有一个实例化T的新实例的方法,如果它是一个“复杂”类,则从一组源数据值中填充其属性。

(a)如果T是简单类型(例如字符串或int或其他类似的东西),则执行从源数据到T的快速转换。

(b)如果T是一个类(但不是像字符串这样简单的东西),那么我将使用Activator.CreateInstance并进行一些反射来填充字段。

是否有一种快速而简单的方法来判断我是否应该使用方法(a)或方法(b)?该逻辑将在通用方法中使用,其中T作为类型参数。

7 个答案:

答案 0 :(得分:103)

字符串可能是一种特殊情况。

我想我会做.....

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

修改

有时您需要覆盖更多案例,例如枚举和小数。枚举是C#中的一种特殊类型。小数是任何其他结构。结构的问题在于它们可能很复杂,它们可能是用户定义的类型,它们可能只是一个数字。因此,除了了解它们之外,你没有任何其他机会。

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

处理可空的对应物也有点棘手。可空的本身就是一个结构。

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));
}

测试:

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 in System.Drawing
Assert.IsFalse(IsSimple(typeof(Point?)));
Assert.IsFalse(IsSimple(typeof(StringBuilder))); // reference type

.NET Core注意事项

正如DucoJ在his answer中指出的那样,一些使用过的方法不再适用于.NET核心中的Type类。

固定代码(我希望它有效,我无法尝试自己。否则请评论):

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

答案 1 :(得分:16)

除了Stefan Steinegger的回答: 在.NET Core中,.IsPrimitive等不再是Type的成员,它们现在是TypeInfo的成员。所以他的解决方案将成为:

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

答案 2 :(得分:5)

有一种比原语更通用的类型,ValueType包含的不仅仅是原语,比如枚举,小数和其他类似的东西ValueType。下面是我写的一个函数,用于识别可能符合您需求的复杂类型。

    public static bool IsComplex(Type typeIn)
    {
        if (typeIn.IsSubclassOf(typeof(System.ValueType)) || typeIn.Equals(typeof(string))) //|| typeIn.IsPrimitive
            return false;
        else
            return true;

    }

答案 3 :(得分:3)

很抱歉复活了一个非常老的帖子,但由于这仍然在Google的网络搜索中排名很高,因此希望获得更直接有效的解决方案:

if(System.Type.GetTypeCode(typeof(int)) == TypeCode.Object) {
    // Do what you will...
}

答案 4 :(得分:1)

这可能无关紧要,但听起来好像你遗漏了几个案例:

  1. 具有转化的复杂类型
  2. 没有无参数构造函数的值类型。示例如下:
  3. 可能还有更多,但我认为你是以过度限制的方式划分问题空间。

     public class Person {
        private string _name;
        private int _age;
        public Person(string name, int age) {_name = name; _age = age;}
        // Remainder of value implementation
     }
    

答案 5 :(得分:1)

使用基于TypeConverter的解决方案也是一种很好的建模方法。

假设您具有此实现:

public static bool IsSimple(this Type type) =>
    TypeDescriptor.GetConverter(type).CanConvertFrom(typeof(string));

这将返回true的以下信息:

  • 所有原始类型
  • 所有枚举
  • string s
  • decimal s
  • DateTime
  • DateTimeOffset
  • TimeSpan
  • Uri
  • Guid
  • Nullable<>以上任何一种类型
  • 已实现本机TypeConverter的许多其他类型(请参阅Derived部分的here

此方法之所以有效,是因为大多数框架本身都支持TypeConverter,例如XML和Json序列化库,然后您可以使用同一转换器在读取时解析值。

答案 6 :(得分:0)

如果我没记错的话,字符串不是原语。即使有一个关键字,字符串也是一个对象。您对IsPrimitive的调用将准确地告诉您某些内容是否是原语。