如何通过反射区分值类型、可空值类型、枚举、可空枚举和引用类型?

4
如何通过反射区分值类型、可空值类型、枚举、可空枚举和引用类型?
enum MyEnum
    {
        One,
        Two,
        Three
    }

    class MyClass
    {
        public int IntegerProp { get; set; }
        public int? NullableIntegerProp { get; set; }
        public MyEnum EnumProp { get; set; }
        public MyEnum? NullableEnumProp { get; set; }
        public MyClass ReferenceProp { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {   
            Type classType = typeof(MyClass);

            PropertyInfo propInfoOne = classType.GetProperty("IntegerProp");
            PropertyInfo propInfoTwo = classType.GetProperty("NullableIntegerProp");
            PropertyInfo propInfoThree = classType.GetProperty("EnumProp");
            PropertyInfo propInfoFour = classType.GetProperty("NullableEnumProp");
            PropertyInfo propInfoFive = classType.GetProperty("ReferenceProp");

            propInfoOne.???
            ...............
            ...............
        }
    }

在propInfo中,这些信息可以被检索到哪里?


你如何定义“基本类型”? - CodesInChaos
整数,浮点数,双精度......正如您在MyClass-props中所看到的。值类型。 - user366312
那么自定义结构体呢?例如,我不明白为什么你要区分枚举和其他值类型。 - CodesInChaos
http://en.csharp-online.net/Common_Type_System%E2%80%94Type_Unification - user366312
以上代码中没有值类型,值类型是一个结构体..这与原始类型不同。 - Myles McDonnell
@MylesMcDonnell int 是一种值类型,int? 也是一种值类型。大多数基元类型都是值类型。 @Saqib 不确定您想通过此链接告诉我们什么。它没有包含您所谓的“基本类型”的定义。它将 DateTime 称为基元,这是错误的。而且我从未听说过 FtnPtr 类型,在内置引用类型下列出了它们。 - CodesInChaos
3个回答

6

以下是如何检查枚举、可空、原始和值类型的方法:

Console.WriteLine(propInfoOne.PropertyType.IsPrimitive); //true
Console.WriteLine(propInfoOne.PropertyType.IsValueType); //false, value types are structs

Console.WriteLine(propInfoThree.PropertyType.IsEnum); //true

var nullableType = typeof (Nullable<>).MakeGenericType(propInfoThree.PropertyType);
Console.WriteLine(nullableType.IsAssignableFrom(propInfoThree.PropertyType)); //true

请注意,值类型和基元类型是不同的东西。 基元类型只是映射到类型的简写(例如bool> System.Boolean)。 值类型按值传递; 它们是结构体而不是类。

1
@Programming Hero:你能告诉我Type.IsPrimitive属性表示什么吗? - Myles McDonnell
2
@ProgrammingHero 这并不完全正确; 原语通常指那些具有直接 IL支持的基本类型; 例如,intshortbytelongfloat等都具有直接 IL支持;例如+这样的运算符不使用类型运算符,而是IL指令。相比之下,例如 decimal不是一个原语。它们被非常不同地对待。实际上,在堆栈上,它们中的大部分甚至不存在: byte,sbyte,short, ushort等在IL级别(在操作期间;而不是作为它们的声明)都使用int - Marc Gravell
2
@Myles - 检查 Nullable<T> 更好的方法是使用 Nullable.GetUnderlyingType - Marc Gravell
1
有人可以评论一下为什么这不是现在的答案吗? - Myles McDonnell
7
我看到你相信了一个谎言,即值类型被存储在栈上。除了几乎从不存储在栈上之外,值类型通常存储在栈上。 - Eric Lippert
显示剩余7条评论

2
    public void Test(Type desiredType, object value)
    {
        if (desiredType.IsGenericType)
        {
            if (desiredType.GetGenericTypeDefinition() == typeof(Nullable<>))
            {
                if (value == null)
                {
                }
            }
        }
    }

0

PropertyType.Name 似乎会针对非空和可空类型提供不同的输出。这可能对您有所帮助。

实际上,它会将 Nullable`1 Int32 作为可空和非可空类型的输出。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接