CLR via C#学习笔记-第十五章-枚举类型
15.1 枚举类型
枚举类型定义了一组"符号名称/值"配对。
例如以下Color类型定义了一组符号,每个符号都表示一种颜色:
internal enum Color{ White,//赋值0 Red,//赋值1 Green,//赋值2 Blue//赋值3 }
使用枚举的好处
①枚举类型是程序更容易编写、阅读和维护。
②枚举是强类型的
枚举的特性
枚举类型在类型系统中是一等公民。每个枚举类型都从System.Enum派生,后者从System.ValueType派生,而System.ValueType又从System.Object派生,所以枚举类型是值类型。
可以未装箱和已装箱的形式来表示。有别于其他值类型,枚举不能定义任何方法、属性、事件。不过可以利用扩展方法模拟向枚举类型添加方法。
枚举的实质
编译枚举时编译器把每个符号转换成类型的一个常量字段,编译器将前面的Color枚举类型看成是以下代码:
internal struct Color:System.Enum{ public const Color White = (Color) 0; public const Color Red = (Color) 1; public const Color Green = (Color) 2; public const Color Blue = (Color) 3; public Int32 value_; }
编译器不会实际编译上述代码,因为他禁止定义从特殊类型System.Enum派生的类型。
简单说,枚举类型只是一个结构,定义了一组常量字段和一个实例字段。
枚举的声明
枚举默认是int类型的,也可以声明为其他基础类型
internal enum Color:byte{ White, Red, Green, Blue }
使用GetUnderlyingType获取枚举类型使用的基础类型
Enum.GetUnderlyingType(typeof(Color));
编译器将枚举类型视为基元类型。可以使用许多操作符来操纵枚举类型的实例。
编译器允许将枚举类型实例显示转换为不同的枚举类型,也可显式将枚举类型实例转型为数值类型。
枚举的值的格式化
给定一个枚举类型的实例,可以调用ToString输出枚举的值或者对应的符号。
Color color = Color.Blue; WriteLine(color);//Blue WriteLine(color.ToString());//Blue WriteLine(color.ToString("G"));//常规,Blue WriteLine(color.ToString("D"));//十进制,3 WriteLine(color.ToString("X"));//十六进制,00000003
除了ToString还有Format方法用来格式化枚举类型的值
public static String Format(Type enum,Object value,String format);//format方法以及参数 Enum.Format(typeof(Color),3,"G");//Blue
Format的优势是允许为value传值,这样就不一定需要有枚举类型的实例。
获取枚举的成员输出在数组里
使用System.Enum的静态方法GetValues或者System.Type的实例方法GetEnumValues来返回一个数组,数组中的每个元素都对应枚举类型中的一个符号名称,每个元素都包含符号名称的数值。
public static Array GetValues(Type enumType);//System.Enum中定义 public Array GetEnumValues();//System.Type中定义
结合ToString方法使用以显示枚举类型中所有符号名称以及对应数值。
Color[] colors =(Color[])Enum.GetValues(typeof(Color)); WriteLine("Number of symbol defined:"+colors.Length); WriteLine("Value\tSymbol\n-----\t------"); foreach (var c in colors) WriteLine($"{c:D}\t{c:G}");//十进制和常规格式显示每个符号 ReadKey();
以上代码输出如下:
Number of symbol defined:4 Value Symbol ----- ------ 0 White 1 Red 2 Green 3 Blue
作者不喜欢有以上两种方法,因为二者均是返回一个Array需要转型成恰当的数组类型,作者选择用自己定义泛型GetEnumValues方法,这样可以获得更好的编译时类型安全性。,上例中的第一句代码可以简化成如下形式
Color[] colors=GetEnumValues<Color>();
根据成员的值获取枚举中对应的符号
除了GetValues方法,还提供了以下方法来返回枚举类型的符号:
//返回数值的字符串表示 public static String GetName(Type enumType,Object value);//Enum中定义 public String GetEnumName(Object value);//Type中定义 //返回一个String数组,枚举中每一个符号都对应一个String public static String[] GetNames(Type enumType);//Enum中定义 public String[] GetEnumNames();//Type中定义
根据符号获取枚举值对应的值
还有查找与符号对应的值的方法:Parse、TryParse,以下代码演示了如何是通用这些方法:
Color c=(Color)Enum.Parse(typeof(Color),"blue",true);//c被初始化为3第三个参数是是否忽视大小写 Color c=(Color)Enum.Parse(typeof(Color),"brown",false);//不存在该符号,报错 Enum.TryParse<Color>("1",false,out c);//创建值为1的Color枚举类型实例
判断值对于某枚举是否合法
Enum的静态isDefined方法和Type的IsEnumDefined方法用于判断数值对于某枚举类型是否合法
public static bool IsDefined (Type enumType, object value); public bool IsEnumDefined(Object value);
Enum提供了一组静态ToObject方法,可以将各种基元类型实例转换为枚举实例。
枚举与需要其的类同级
枚举通常需要与需要他的类同级,是为了减少代码的录入量。
15.2 位标志
调用System.IO.File类型的GetAttributes方法,返回FileAttributes类型的一个实例。
FileAttributes类型是基本类型为int的枚举类型,其中每一位都反应了文件的一个特性。
15.3 向枚举类型添加方法
现在可以利用扩展方法模拟向枚举类型添加方法。