写在前面
枚举Enum 全称(Enumeration),即一种由一组称为枚举数列表的命名常量组成的独特类型。能够看出枚举的出现时为了使咱们能够在程序中方便的使用一些特定值的常量,通常的使用你们都比较熟悉,本文主要介绍枚举的特性 FlagAttribute。测试
FlagAttribute是什么?
Flag 特性微软的解释是:指示能够将枚举做为位域(即一组标志)处理,FlagsAttribute属性就是枚举类型的一项可选属性,它的主要做用是能够将枚举做为位域处理(P.S. C#不支持位域)。所谓位域是单个存储单元内相邻二进制位的集合。经过为枚举添加这个属性,能够改变枚举的一些行为来知足咱们的须要。编码
好比咱们有以下枚举的定义:url
public enum OrderTypeEnum { Init, Complete, Waiting, Paid }
逻辑或操做我相信你们都比较熟悉了,对于整数来讲,| 操做就是将其转化为二进制再进行或运算。OrderTypeEnum.Init | OrderTypeEnum.Complete作的工做其实是 0001 | 0010 = 0011 = 3再转换成(OrderTypeEnum)3就是OrderTypeEnum.Paid了.spa
若是咱们对两个枚举值作 | 操做,那结果会是什么样呢?.net
OrderTypeEnum result = OrderTypeEnum.Waiting | OrderTypeEnum.Paid;
按照或操做的原理:0010 | 0011 = 0011(3) Paid ,实质上咱们想要的结果是想讲两个枚举值都做为或操做的结果,可是由于枚举值默认是从0开始顺次递增的,那么通过或操做以后就得不到咱们想要的结果,那怎么办呢,这时候就须要 给枚举加上 [Flags] 的Attribute,咱们先来看一下FlagsAttribute定义的准则:code
- 使用FlagsAttribute枚举才是对数字值执行按位运算 (AND、 OR 独占或) 的自定义属性。
- 在 2 的幂,即 一、 二、 四、 8 等中定义枚举常量。 这意味着不重叠中组合的枚举常量的各个标志。
- 请考虑建立针对经常使用的标志组合的枚举的常数。 例如,若是你有用于文件 I/O 操做的枚举包含枚举的常数Read = 1和Write = 2,请考虑建立枚举的常数ReadWrite = Read OR Write,它结合Read和Write标志。 此外,可用于组合标志的按位 OR 操做视为在某些状况下,不该为用于简单任务所需的一个高级的概念。
- 若是为标志枚举常量中定义为负数,由于不少标志位置可能会设置为 1,这可能会使你的代码的混乱,并鼓励编码错误,请务必当心。
- 测试是否在数值中设置一个标志一种简便方式是执行按位,操做之间的数字值和标志枚举的常数,它将全部位都设置为不对应于标志的零的数字值中,而后测试该操做的结果是否等于该标志枚举常量。
- 使用None用做枚举其值为零的常量的标志名称。 不能使用None按位运算中,来测试一个标志,由于结果始终为零的枚举的常数。 可是,你能够执行的逻辑不之间的数字值的按位、 比较和None枚举的常量,以肯定是否已设置在数值中的任何位。
- 若是你建立而不是标志枚举的值枚举,它是仍必要建立None枚举的常数。 缘由是,默认状况下用于枚举的内存初始化为零的公共语言运行时。 所以,若是未定义其值为零的常量,枚举将包含在建立时非法值。
- 若是你的应用程序须要表示明显默认状况下,请考虑使用其值为零表示默认值的枚举的常数。 若是没有任何默认状况下,请考虑使用其值为零的枚举的常数意味着不禁任何其余枚举常量表示这种状况。
- 未定义一个枚举值,只是为了镜像与枚举自己的状态。 例如,不定义仅用于枚举的结束标记的枚举的常数。 若是你须要肯定在枚举的最后一个值,请显式检查该值。 此外,你能够执行范围检查第一个和最后一个枚举常量,若是范围内的全部值都是有效。
- 不要指定保留供未来使用的枚举的常数。
- 当你定义的方法或属性,它采用做为值的枚举的常数时,请考虑验证值。 缘由是,即便该数值不在枚举中定义,你能够强制转换为枚举类型的数字值。
咱们看到第二句告诉咱们当加了Flags的特性以后默认的枚举值就会以2的幂一次递增,好比 20,21,22,23(1,2,4,8....)blog
那咱们从新看一下从新定义以后的或操做会是什么结果呢?内存
[Flags] public enum OrderTypeEnum { Init, Complete, Waiting, Paid }
此时咱们再来看:OrderTypeEnum result = OrderTypeEnum.Complete | OrderTypeEnum.Waiting | OrderTypeEnum.Paid ;get
0010 | 0100 | 1000 = 1110 咱们能够看到实质上就是作了二进制的或运算,将全部位值作了合并it
当咱们能够用作位运算的时候,就不只仅是或,与,非,异或等操做均可以实现。
咱们知道经过这样能够把枚举值合并 OrderTypeEnum result = OrderTypeEnum.Complete | OrderTypeEnum.Waiting | OrderTypeEnum.Paid ;
那么同理也能够来判断这样的集合中是否包含某个枚举值:
result.HasFlag(OrderTypeEnum.Paid)
写在最后
枚举经过添加Flags的特性使得它可以拥有位运算的能力,更方便了咱们再平常代码中的使用。
参考资料:http://www.alanzucconi.com/2015/07/26/enum-flags-and-bitwise-operators/