12.1 枚举类型
强类型,枚举之间进行不能隐式转换
枚举类型直接派生于System.Enum,后者派生于System.ValueType,值类型,可以使用装箱/拆箱
不能定义方法/属性/事件。
枚举类型要与使用它的类在同一级。
默认为int,可以指定枚举成员的类型,只有int,uint,byte,sbyte,long,ulong,short,ushort这8种基元类型。
可以使用操作符作用于枚举类型,实际上是作用于相应的value实例字段,如++。
可以将枚举类型的实例显示转型为另一个不同的枚举类型,其实是先转为值,再反过去在另一个枚举中根据值找对应枚举值。
可以显示将枚举类型的实例转型为一个数值类型。
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedBlockEnd.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedBlockEnd.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](/Images/OutliningIndicators/ExpandedBlockEnd.gif)
如 enum Color{Red=1, White=2}对应IL:
可以看到,枚举只是一个在其中定义一系列常量字段和实例字段的结构。
如果只使用Color.Red这样的类型,则会作为常量处理,从而代码不再引用定义了的枚举类型,可以删除相应的dll(具体见第7章);
如果使用Color c = new Color();这样的语法,那么依赖于引用,不可以删除相应的dll
枚举方法列表:
1.GetUnderlyingType静态方法,获取枚举类型值的核心类型:
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
2.ToString()方法
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
对于c.ToString("X")十六进制格式,A-F始终是大写字母。此外,输出的数位个数取决于Color的基本类型:
byte/sbyte 2位
short/ushort 4位
int/uint 8位
long/ulong 16位
3.Format静态方法,功能基本同ToString()方法,但允许value传递一个数值,而不仅仅是一个Enum类型
![](/Images/OutliningIndicators/None.gif)
4.GetValues静态方法,返回一个数组,数组中为所有的枚举类型名称:
![](/Images/OutliningIndicators/None.gif)
5.static String GetName(Type enumType, Objbect value)静态方法,返回数值的字符串表示
6.static String[] GetNames(Type enumType),返回方法5的数组表示
7.Parse静态方法,将一个符号转换为枚举类型的一个实例:
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
8.IsDefined静态方法,判断一个数值对于一个枚举类型是否合法:
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
常用于参数验证:
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedSubBlockEnd.gif)
![](/Images/OutliningIndicators/ExpandedBlockEnd.gif)
注:Enum.IsDefined方法慎用,因为要区分大小写查找;使用反射机制,速度慢。
9.ToObject静态方法,一系列方法,如Enum.ToObject (Type, Byte),将Int32,Byte等类型实例转为枚举类型的实例(由于返回都是Object,所以要显示转型)
12.2 位标志 bit flag
位标志是一个位集合,其中有些位on,有些位off;而枚举是一个数值,是位集合中若干值的累加。
在枚举上应用[Flags]属性,就可以用枚举来表示一组可以组合的位标志,一般要定义一个值为0的None符号。
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/InBlock.gif)
![](/Images/OutliningIndicators/ExpandedBlockEnd.gif)
这时,就可以使用位运算来操作:
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/ExpandedBlockStart.gif)
逻辑或,组合出所需的枚举列表,一般用来设置:
![](/Images/OutliningIndicators/None.gif)
对位标记Enum调用ToString()方法,数值转字符串:
先检查是否应用了[Flags]属性
如果没有,就查找与该数值匹配的Enum符号并返回,没有匹配就返回数值。
如果有,就获取Enum降序排列的数值集合A,将A中的数值“按位与”Enum实例中的数值,将结果等于数值的Enum项附加到输出字符串,以逗号分割,如"Read,Write"
有两种特殊情况:
1.一个数值不能由Enum的若干项组合,则返回该数值
2.应该定义0。
对位标记Enum调用Parse()方法,字符串转数值:
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
![](/Images/OutliningIndicators/None.gif)
处理过程如下:
1.删除字符串中所有空白字符
2.如果字符串以+/-/数字开始,那么字符串被认为是一个数字,直接转型为对应数值的字符串
3.以逗号分割字符串,在Enum中查找相应符号的数值,按位或取值并返回
不要对位标记Enum调用IsDefined()方法,因为,
传字符串,位标记中含有逗号,但永远找不到含有逗号的枚举符号;
传数值,永远返回false