枚举类型是值类型,System.Enum是引用类型
首先需要明白的一点是,所有的枚举类型都隐式继承于System.Enum抽象类,如下所示,
定义一个名为Test的枚举类型:
enum Test:long
{
Test1,
Test2
}
然后查看它的IL代码:
.class private auto ansi sealed Test
extends [mscorlib]System.Enum
{
.field public static literal valuetype Test Test1 = int64(0x0)
.field public static literal valuetype Test Test2 = int64(0x0)
.field public specialname rtspecialname int64 value__
}
通过IL代码,我们可以很清楚的看到,定义的枚举类型Test继承自System.Enum类,只不过这里是隐式继承,由编译器来实现的。而System.Enum类又是继承自System.ValueType类(显示继承),微软对System.ValueType的定义为:提供值类型的基类,很显然枚举类型属于值类型,下面对其进行验证:
static void Main(string[] args)
{
Type t=typeof(Test);
if(t.IsValueType)// t.IsEnum同样会输出Yes
{
Console.WriteLine("Yes");
Console.ReadLine();
}
}
上面的代码会成功输出“Yes”,说明枚举类型的确是值类型(当然他也是枚举类型)。
读者可能会有疑问,System.Enum同样是继承自System.ValueType,它为什么不是值类型呢?这个问题其实很简单,那是因为微软就是这么规定的,全当他是一个特例,呵呵。读者可以研究一下struct类型,用struct关键字定义结构类型的时候,编译器同样进行了隐式继承,继承的类恰好就是System.ValueType。至于为什么一种类型继承自引用类型,而他本身却是值类型,大家不必深究,微软就是这么规定的,MS也许也是怕产生歧义才采用隐式继承的吧。对于System.Enum,大家看如下的代码:
static void Main()
{
Type t = typeof(System.Enum);
if (t.IsEnum)
Console.WriteLine("I'm enum type.");
if (t.IsValueType)
Console.WriteLine("I'm value type.");
}
运行上面的程序,你会发现什么都不会输出,验证了上面的说法(它不是值类型,更不是枚举类型)。
还有一点需要注意的是,上面在定义Test的时候,明明继承了long,但是IL代码里面并没有相应的继承代码,而是在结构内部定义了一个long类型的特殊字段。虽然我们定义Test的时候形式上是继承了long类型,但是编译器会对其进行特殊处理,不会将其视为继承来对待。
网上还有很多关于“枚举”的博客,大家可以搜“有关C#枚举的问答集锦”,一共有三篇,上面对枚举进行了深入细致的分析和讲解。