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作为类型参数。
答案 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)
这可能无关紧要,但听起来好像你遗漏了几个案例:
可能还有更多,但我认为你是以过度限制的方式划分问题空间。
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的调用将准确地告诉您某些内容是否是原语。