C#6.0语言规范(十四) 枚举
一个枚举类型是一个独特的值类型(值类型)声明一组命名的常量。
这个例子
1 enum Color 2 { 3 Red, 4 Green, 5 Blue 6 }
声明了一个名为枚举类型Color
与成员Red
,Green
和Blue
。
枚举声明
枚举声明声明了一个新的枚举类型。枚举声明以关键字开头enum
,并定义枚举的名称,可访问性,基础类型和成员。
1 enum_declaration 2 : attributes? enum_modifier* 'enum' identifier enum_base? enum_body ';'? 3 ; 4 5 enum_base 6 : ':' integral_type 7 ; 8 9 enum_body 10 : '{' enum_member_declarations? '}' 11 | '{' enum_member_declarations ',' '}' 12 ;
每个枚举类型都有一个相应的整数类型,称为枚举类型的基础类型。此基础类型必须能够表示枚举中定义的所有枚举器值。enum声明可以显式地声明基础类型的byte
,sbyte
,short
,ushort
,int
,uint
,long
或ulong
。请注意,char
不能用作基础类型。未明确声明基础类型的枚举声明具有基础类型int
。
这个例子
1 enum Color: long 2 { 3 Red, 4 Green, 5 Blue 6 }
声明一个基础类型为的枚举long
。开发人员可能会选择使用基础类型(long
如示例中所示)来启用范围内long
但不在范围内的值int
,或者为将来保留此选项。
枚举修饰符
一个enum_declaration可任选地包括枚举改性剂的一个序列:
1 enum_modifier 2 : 'new' 3 | 'public' 4 | 'protected' 5 | 'internal' 6 | 'private' 7 ;
同一修饰符在枚举声明中多次出现是编译时错误。
枚举声明的修饰符与类声明(类修饰符)的含义相同。但请注意,枚举声明中不允许使用abstract
和sealed
修饰符。枚举不能是抽象的,也不允许派生。
枚举成员
枚举类型声明的主体定义零个或多个枚举成员,它们是枚举类型的命名常量。没有两个枚举成员可以具有相同的名称。
1 enum_member_declarations 2 : enum_member_declaration (',' enum_member_declaration)* 3 ; 4 5 enum_member_declaration 6 : attributes? identifier ('=' constant_expression)? 7 ;
每个枚举成员都有一个关联的常量值。此值的类型是包含枚举的基础类型。每个枚举成员的常量值必须在枚举的基础类型的范围内。这个例子
1 enum Color: uint 2 { 3 Red = -1, 4 Green = -2, 5 Blue = -3 6 }
导致编译时错误,因为在恒定的值-1
,-2
和-3
不在底层积分类型的范围uint
。
多个枚举成员可以共享相同的关联值。这个例子
1 enum Color 2 { 3 Red, 4 Green, 5 Blue, 6 7 Max = Blue 8 }
显示一个枚举,其中两个枚举成员 - Blue
和Max
- 具有相同的关联值。
枚举成员的关联值是隐式或显式指定的。如果枚举成员的声明具有constant_expression初始值设定项,则该常量表达式的值(隐式转换为枚举的基础类型)是枚举成员的关联值。如果枚举成员的声明没有初始值设定项,则隐式设置其关联值,如下所示:
- 如果枚举成员是枚举类型中声明的第一个枚举成员,则其关联值为零。
- 否则,通过将文本上在前的枚举成员的关联值增加1来获得枚举成员的关联值。此增加的值必须在可由基础类型表示的值范围内,否则会发生编译时错误。
这个例子
1 using System; 2 3 enum Color 4 { 5 Red, 6 Green = 10, 7 Blue 8 } 9 10 class Test 11 { 12 static void Main() { 13 Console.WriteLine(StringFromColor(Color.Red)); 14 Console.WriteLine(StringFromColor(Color.Green)); 15 Console.WriteLine(StringFromColor(Color.Blue)); 16 } 17 18 static string StringFromColor(Color c) { 19 switch (c) { 20 case Color.Red: 21 return String.Format("Red = {0}", (int) c); 22 23 case Color.Green: 24 return String.Format("Green = {0}", (int) c); 25 26 case Color.Blue: 27 return String.Format("Blue = {0}", (int) c); 28 29 default: 30 return "Invalid color"; 31 } 32 } 33 }
打印出枚举成员名称及其相关值。输出是:
1 Red = 0 2 Green = 10 3 Blue = 11
原因如下:
- 枚举成员
Red
被自动赋值为零(因为它没有初始值并且是第一个枚举成员); - 枚举成员
Green
被明确赋予值10
; - 并且枚举成员
Blue
被自动分配的值大于文本上位于其前面的成员。
枚举成员的关联值不能直接或间接使用其自己的关联枚举成员的值。除了这种循环限制之外,枚举成员初始化器可以自由地引用其他枚举成员初始化器,而不管它们的文本位置如何。在枚举成员初始值设定项中,其他枚举成员的值始终被视为具有其基础类型的类型,因此在引用其他枚举成员时不需要强制转换。
这个例子
1 enum Circular 2 { 3 A = B, 4 B 5 }
导致编译时错误,因为声明A
和B
是循环的。A
取决于B
明确,并B
取决于A
隐含。
枚举成员的命名和范围与类中的字段完全类似。枚举成员的范围是其包含枚举类型的主体。在该范围内,枚举成员可以通过其简单名称来引用。在所有其他代码中,枚举成员的名称必须使用其枚举类型的名称进行限定。枚举成员没有任何声明的可访问性 - 如果枚举成员的包含枚举类型可访问,则可以访问该成员。
System.Enum类型
类型System.Enum
是所有枚举类型的抽象基类(这与枚举类型的基础类型不同且不同),并且继承自的成员System.Enum
在任何枚举类型中都可用。装箱转换(装箱转换)从任何枚举类型来存在System.Enum
,和取消装箱转换(解包转换)从存在System.Enum
于任何枚举类型。
请注意,System.Enum
它本身不是enum_type。相反,它是一个class_type,从中派生所有enum_type。该类型System.Enum
继承自类型System.ValueType
(System.ValueType类型),而类型继承自类型object
。在运行时,type的值System.Enum
可以是null
或对任何枚举类型的盒装值的引用。
枚举值和操作
每个枚举类型定义一个不同的类型; 在枚举类型和整数类型之间或两个枚举类型之间进行转换需要显式枚举转换(显式枚举转换)。枚举类型可以采用的值集不受其枚举成员的限制。特别是,枚举的基础类型的任何值都可以强制转换为枚举类型,并且是该枚举类型的唯一有效值。
枚举成员具有包含枚举类型的类型(在其他枚举成员初始值设定项中除外:请参阅枚举成员)。枚举成员的值枚举类型中声明E
相关联的值v
是(E)v
。
以下运算符可以在枚举类型的值可以使用:==
,!=
,<
,>
,<=
,>=
(枚举比较运算符),二进制+
(加法运算符),二进制-
(减法运算符), ,^
,(&
枚举逻辑运算符), (按位求补运算符),并(后缀增量和减量运算符以及前缀增量和减量运算符)。|
~
++
--
每个枚举类型都自动派生自类System.Enum
(反过来,派生自System.ValueType
和object
)。因此,此类的继承方法和属性可用于枚举类型的值。