枚举类型和位标志

枚举类型和位标志
枚举类型

internal enum Color

{

White,  //赋值0

Red,   //赋值1

Blue   //赋值2

}

编码时,不应将数字硬编码到代码中,与符号对应的值发生变化,代码简单的重新编译就可,不用对源代码修改,枚举是强类型。

每个枚举类型是从System.Enum派生,后者又从System.ValueType派生,其又从System.Object派生。

编译枚举类型时,C#编译器会把每个符号转换成该类型的一个常量字段,它会把代码当做下面的代码处理:

internal struct Color : System.Enum

{

public const Color White = (Color) 0 ;
 
public Int32 value__;  //包含一个Color变量的值,不能直接引用这个实例字段

}

枚举类型可以看做只是其中定义一系列常量字段和实例字段的结构。常量字段会成为程序集的元数据,通过反射机制来访问,可以在枚举类型关联的所有符号和值之间转换。System.Enum类提供了几个静态方法和实例方法,来操作枚举的实例,而不会使用反射。
 
public static Type GetUnderlyingType(Type enumType);

返回用于容纳枚举类型值的核心类型。每个枚举都有一个基本类型,可以是byte , sbyte , short , int(默认)等 

internal enum Color : byte {}

Console.Write(Enum.GetUnderlyingType(typeof(Color)));  //  byte

C#编译器把枚举类型当做基元类型来处理,因此可以用==,!=等操作符,还允许显式转换不同的枚举类型的实例,也可显式的或隐式的转换为数值类型。

ToString()

Color c = Color.Blue ;

Console.WriteLine(c.ToString());   //Blue

Console.WriteLine(c.ToString(“G”));  //泛型格式,Blue ,还可用D 十进制格式3,X十六进制03

public static String Format(Type  enumType , Object vlaue , String format ) ;

Console.Write(Enum.Format(typeof(Color) , 3 , “G” ));    //  Blue

public static Array GetValues(Type enumType);  //  返回的数组每个元素对应于枚类型中的一个符号名称

public static String GetName(Type enumType , Object value );   //  返回数值对应的字符串表示

public static String[] GetNames(Type enumType );  // 返回一个String数组,每个符号对应一个String

用于查找与符号对应的数值Parse

public static Object Parse(Type enumType , String value);

public static Object Parse(Type enumType , String value , Boolean , ignoreCase);

这个vlaue若可转换为数值,则就会转换成数值型

还有一个

public static Boolean IsDefined(Type enumType , Object value);

可以传入符号值或数值,查找是否在枚举类型中定义了这个值

还有静态方法ToObject,将Byte , int类型实例转换为枚举类型实例
 
位标志

如System.IO.File类型的GetAttributes方法,返回FileAttributes类型的实例,它是一个类型为Int32的枚举类型,其中每一位(每个bit)都反映了文件的一个属性。

[Flags , Serializable ]

public enum FileAttributes

{

ReadOnly = 0x0001,

Hidden = 0x0002,

System = 0x0004,

……

}

用枚举类型来表示一组可以组合的位标志,枚举类型只表示单个数值,而位标志表示一个集合,其中有些位on,有些位off .

定义用于位标志的枚举类型,应显式的为每个符号指定一个数值,每个符号都有一个单独的位on .经常还定义值为0的None符号,还可定义一此用于组合的符号,

[Flags]   //C#编译器允许使用Flags

internal enum Actions

{

None = 0 ,

Read = 0x0001 ,

Write = 0x0002 ,

ReadWrite = Actions.Read | Actions.Write ,

Delete = 0x0004,

……

}
 
Actions ac = Actions.Read | Actions.Write ;   //0x0005

Console.WriteLine(ac.ToString());      //   Read , Delete
 
ToString()试图将数值转换为符号,而0x0005没有对应的符号,但是方法检测到类型上存在Flags属性,就不会将它看做一个单独的数值了,而看做一组位标志。仍可以用G,D,X来格式化。

如果枚举类型没有应用Flags属性时,就查找与该数值匹配的符号,如果应用了,工作过程:

1,  获得枚举类型定义的数值集合,并按降序排列这些数值

2,  每个数值都与枚举实例中的值进行“按位与”操作,如结果等于数值,与该数值关联的字符串就附加到输出字符串之后,该位被除数视为已计算,并会被关闭。不断重复,直到检查完所有数值,或枚举实例的所有位都关闭

3,  之后,如果枚举实例仍然不为0,表明枚举实例中一些处于on状态的位不对应于任何已定义的符号,此时,将枚举实例的数值作为一个字符串返回。

4,  如枚举实例的原始值不为0,就返回各符号之间用逗号分隔的字符串

5,  如果枚举实例的原始值为0,而且枚举类型定义的一个符号的对应值是0,返回这个符号

6,  到这一步时,返回0
 
如果没有用Flags属性,仍然可用标志F来实现:

Console.WriteLine(actions.ToString(“F”)); //  Read , Write
 
将用逗号分隔的字符串转换为数值Enum.Parse

Actions a = (Actions)Enum.Parse((typeof(Actions), “Write , Read” , false);  // 3

Parse方法调用时

1,  从头到尾删除字符中的所有空白字符

2,  如果字符串的第一个字符是数字、加号、减号,该字符串会被认为一个数字,就返回一个枚举实例,其值等于对应数值的字符串

3,  传递的字符串被划分为一个token集合,每个token的空白被去掉

4,  在枚举实例中已定义的符号中查找每个token字符串,没有找到就抛出一个System.ArgumentException异常,找到就对其数值进行“按位与”操作,把它添加到结果中,然后查找下一个符号

5,  查找完,返回结果
 
另外,不要对位标志使用IsDefined方法,因为传递字符串时,它不会将字符串拆分为token,若传入的是数值,只查找与之匹配的传入的符号,不会应用位标志本身。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值