枚举类型和位标志
| 1. | 枚举类型 |
| 2. | 位标志 |
| 3. | 为枚举类型添加方法 |
枚举类型
定义了一组“符号名称/值”配对
例如:Color类型的一组符号,每一种代表一种颜色,以下没有特殊说明都用此枚举类型
internal enum Color{
White, //赋值0
Red, //1
Green, //2
Blue, //3
Orange //4
}
为什么使用枚举类型?
1.枚举类型使程序更易编写、阅读、和维护。
2.枚举是强类型的,例如,试图将Color.Orange作为一个值传递给要求Fruit枚举类型作为参数的方法,编译器会报错
意思是说Fruit枚举类型应该是水果,而Color枚举定义的是颜色,虽然两个枚举都有一个Orange,但分别代表的是橙子和橙色。
public static Type GetUnderlyingType(Type enumType); //System.Enum中定义
public Type GetEnumUnderlyingType(); //System.Type中定义
这些方法用来返回用于容纳一个枚举类型的值的基础类型。
每个枚举都有一个基础类型,它可以是byte、sbyte、short、ushort、int(最常用的,也是C#默认选择的)、uint、long或unlong
虽然这些C#基元类型都有对应的FCL类型(注:不要混淆“基础类型”和“基元类型”)
但C#编译器为了简化本身的实现,要求只能指定基元类型名称,如果使用FCL类型名称(比如Int32),会报错。
例如:声明一个基础类型为byte的枚举类型
internal enum Color:byte{
White,
Red,
Green,
Blue,
Orange
}
Console.WriteLine(Enum.GetUnderlyingType(typeof(Color)));
输出:System.Byte
可以调用System.Enum的静态方法GetValues或者System.Type的实例方法GetEnumValues获取一个数组,该数组的每个元素都对应枚举类型中的一个符号名称,
每个元素都包含符号名称的数值。
public static Array GetValues(Type enumType); //System.Enum
public Array GetEnumValues(); //System.Type
利用ToString方法使用,可以显示枚举类型中的所有符号名称及对应的数值。如下所示:
Color[] color =(Color[]) Enum.GetValues(typeof(Color));
Console.WriteLine("Value\tSymbols\n-----\t-------");
foreach (Color cc in color)
{
//以十进制和常规格式显示每个符号
Console.WriteLine("{0,5:D}\t{0:G}",cc);
}
/*输出:*
* Value Symbols
----- -------
0 White
1 Red
2 Green
3 Blue
4 Orange
*
*/
除了GetValues方法,System.Enum和System.Type类型还提供了以下方法来返回枚举的符号:
//返回数值的字符串表示
public static String GetName(Type enumType,Object value); //System.Enum中定义
public String GetEnumName(Object value); //Syste.Type 中定义
//返回一个String数组。枚举每个符号都对应一个String
public static String[] GetNames(Type enumType); //System.Enum中定义
public String[] GetEnumNames(); //Syste.Type 中定义
//通过符号查找对应的值
//enumType:枚举类型、value:符号、ignoreCase:是否忽略大小写
public static Object Parse(Type enumType,String value);
public static Object Parse(Type enumType,String value,Boolean ignoreCase);
public static Boolean TryParse<TEnum>(String value,out TEnum result) where TEnum:struct
public static Boolean TryParse<TEnum>(String value,Boolean ignoreCase, out TEnum result) where TEnum:struct
如何使用上面这些方法:
Color c1 = (Color)Enum.Parse(typeof(Color), "red", true);
// c1 = (Color)Enum.Parse(typeof(Color), "red222", false);//因为没有定义red222所以抛出ArgumentException异常
Enum.TryParse<Color>("1", false,out c1);
Enum.TryParse<Color>("23", false, out c1);
IsDefined方法判断一个数值对于一个枚举类型是否合法:
public static Boolean IsDefined(Type enumType,Object value); //System.Enum中定义
public Boolean IsEnumDefined(Object value); //Syste.Type 中定义
//True,因为Color将Red定义为1
Console.WriteLine(Enum.IsDefined(typeof(Color),1));
//True,因为Color将White定义为0
Console.WriteLine(Enum.IsDefined(typeof(Color), "White"));
//False,区分大小写
Console.WriteLine(Enum.IsDefined(typeof(Color), "white"));
IsDefine方法被经常用于参数校验,例如:
public void SetColor(Color c){
if(!Enum.IsDefined(typeof(Color),c)){
throw new ArgumentOutOfRangeException("c")
}
}
参数校验是非常有用的功能,因为其他人可能向下面这样调用SetColor:
SetColor((Color),547);
没有和值547对应的符号,所以抛出一个异常,注意IsDefined它是区分大小写的,而且它是通过反射原理,性能下降
位标志
位操作符:&和|
FileAttributes类型在FCL中的定义:
[Flags, Serializable]
public enum FileAttributes {
ReadOlny =0x0001,
Hidden =0x0002,
System =0x0004,
Directory =0x0010,
Archive =0x0020,
Device =0x0040,
Normal =0x0080,
Temporary =0x0100,
SparseFile =0x0200
//.....
}
String file = Assembly.GetEntryAssembly().Location;
FileAttributes attribute = File.GetAttributes(file);
Console.WriteLine("Is {0} hidden ? {1}",file,(attribute&FileAttributes.Hidden)!=0);
//将一个文件属性改为只读和隐藏
File.SetAttributes(file, FileAttributes.ReadOnly | FileAttributes.Hidden);
正如FileAttributes类型展示的那样,经常都要用枚举类型来表示一组可以组合的位标识。不过,虽然枚举类型和位标识相似,但它们的语义不尽相同。
例如,枚举类型表示单个数值,而位标识表示一组位,其中一些位处于on状态,有些位处于off状态。
定义用于标识位标志的枚举类型时,当然应该显示为每一个符号分配一个数值,通常,每个符号都有单独的一个位处于on状态,此外,经常都要定义一个值为
0的None符号。还可以定义一些代表用位组合的符号,另外强烈建议向枚举类型应用System.FlagsAttributes这个定制的attribute类型
[Flags]
internal enum Actions{
None=0,
Read=0x0001,
Write=0x0002,
ReadWrite=Actions.Read|Actions.Write,
Delete =0x0004,
Query=0x0008,
Sync=0x0010
}
因为Actions是枚举类型,所以在操作位标志枚举类型时,例如:
Actions actions=Actions.Read|Actions.Delete; //0x0005
Console.WriteLine(actions.ToString()); //Read,Delete
在调用ToString时,它会试图将数值转为对应的符号。现在的数值是0x0005没有对应的符号,不过ToString 方法检测到Actions类型上存在[Flags]这个attribute,所以ToString方法不会将该数值视为单独的值,相反,会把它视为一组位标识。由于0x0005由0x0004和0x0001组合而成,所以ToString会生成字符串Read,Delete,如果没有Flags,ToString会返回5
向枚举类型添加方法
internal static class FileAttributesExtensionMethods{
//模拟一个包含扩展方法的静态类
}
浙公网安备 33010602011771号