C#中枚举的特性FlagAttribute详解
写在前⾯
田艾枚举Enum 全称(Enumeration),即⼀种由⼀组称为枚举数列表的命名常量组成的独特类型。可以看出枚举的出现时为了使我们可以在程序中⽅便的使⽤⼀些特定值的常量,⼀般的使⽤⼤家都⽐较熟悉,本⽂主要介绍枚举的特性 FlagAttribute。
FlagAttribute是什么?扮演用英语怎么说
Flag 特性微软的解释是:指⽰可以将枚举作为位域(即⼀组标志)处理,FlagsAttribute属性就是枚举类型的⼀项可选属性,它的主要作⽤是可以将枚举作为位域处理(P.S. C#不⽀持位域)。所谓位域是单个存储单元内相邻⼆进制位的集合。通过为枚举添加这个属性,可以改变枚举的⼀些⾏为来满⾜我们的需要。
⽐如我们有如下枚举的定义:
public enum OrderTypeEnum
{
Init,
Complete,
Waiting,
Paid
}
逻辑或操作我相信⼤家都⽐较熟悉了,对于整数来说,| 操作就是将其转化为⼆进制再进⾏或运算。OrderTypeEnum.Init | OrderTypeEnum.Complete做的⼯作实际上是 0001 | 0010 = 0011 = 3再转换成(OrderTypeEnum)3就是OrderTypeEnum.Paid 了.
如果我们对两个枚举值做 | 操作,那结果会是什么样呢?
OrderTypeEnum result = OrderTypeEnum.Waiting | OrderTypeEnum.Paid;
按照或操作的原理:0010 | 0011 = 0011(3) Paid ,实质上我们想要的结果是想讲两个枚举值都作为或操作的结果,但是因为枚举值默认是从0开始顺次递增的,那么经过或操作之后就得不到我们想
要的结果,那怎么办呢,这时候就需要给枚举加上[Flags] 的Attribute,我们先来看⼀下FlagsAttribute定义的准则:
1. 使⽤FlagsAttribute枚举才是对数字值执⾏按位运算(AND、 OR 独占或)的⾃定义属性。
2. 在 2 的幂,即 1、 2、 4、 8 等中定义枚举常量。这意味着不重叠中组合的枚举常量的各个标志。
水果西瓜3. 请考虑创建针对常⽤的标志组合的枚举的常数。例如,如果你有⽤于⽂件 I/O 操作的枚举包含枚举的常数Read = 1和
Write = 2,请考虑创建枚举的常数ReadWrite = Read OR Write,它结合Read和Write标志。此外,可⽤于组合标志的按位 OR 操作视为在某些情况下,不应为⽤于简单任务所需的⼀个⾼级的概念。
4. 如果为标志枚举常量中定义为负数,因为很多标志位置可能会设置为 1,这可能会使你的代码的混乱,并⿎励编码错
误,请务必⼩⼼。
5. 测试是否在数值中设置⼀个标志⼀种简便⽅式是执⾏按位,操作之间的数字值和标志枚举的常数,它将所有位都设置为
不对应于标志的零的数字值中,然后测试该操作的结果是否等于该标志枚举常量。
6. 使⽤None⽤作枚举其值为零的常量的标志名称。不能使⽤None按位运算中,来测试⼀个标志,因为结果始终为零的枚
举的常数。但是,你可以执⾏的逻辑不之间的数字值的按位、⽐较和None枚举的常量,以确定是否已设置在数值中的任何位。
7. 如果你创建⽽不是标志枚举的值枚举,它是仍必要创建None枚举的常数。原因是,默认情况下⽤于枚举的内存初始化
为零的公共语⾔运⾏时。因此,如果未定义其值为零的常量,枚举将包含在创建时⾮法值。
8. 如果你的应⽤程序需要表⽰明显默认情况下,请考虑使⽤其值为零表⽰默认值的枚举的常数。如果没有任何默认情况
下,请考虑使⽤其值为零的枚举的常数意味着不由任何其他枚举常量表⽰这种情况。
9. 未定义⼀个枚举值,只是为了镜像与枚举本⾝的状态。例如,不定义仅⽤于枚举的结束标记的枚举的常数。如果你需要
确定在枚举的最后⼀个值,请显式检查该值。此外,你可以执⾏范围检查第⼀个和最后⼀个枚举常量,如果范围内的所有值都是有效。
10. 不要指定保留供将来使⽤的枚举的常数。同性恋怎么过夫妻生活
11. 当你定义的⽅法或属性,它采⽤作为值的枚举的常数时,请考虑验证值。原因是,即使该数值不在枚举中定义,你可以
骷髅头图片
强制转换为枚举类型的数字值。
我们看到第⼆句告诉我们当加了Flags的特性之后默认的枚举值就会以2的幂⼀次递增,⽐如
20,21,22,23(1,2,4,8....)
那我们重新看⼀下重新定义之后的或操作会是什么结果呢?
[Flags]
public enum OrderTypeEnum不顾一切造句
{
Init,
Complete,
Waiting,
Paid
}
此时我们再来看:OrderTypeEnum result = OrderTypeEnum.Complete | OrderTypeEnum.Waiting | OrderTypeEnum.Paid ; 0010 | 0100 | 1000 = 1110 我们可以看到实质上就是做了⼆进制的或运算,将所有位值做了合并
当我们可以⽤做位运算的时候,就不仅仅是或,与,⾮,异或等操作都可以实现。
朋友网登录我们知道通过这样可以把枚举值合并 OrderTypeEnum result = OrderTypeEnum.Complete | OrderTypeEnum.Waiting | OrderTypeEnum.Paid ;
那么同理也可以来判断这样的集合中是否包含某个枚举值:
人鱼线女生
result.HasFlag(OrderTypeEnum.Paid)
写在最后
枚举通过添加Flags的特性使得它能够拥有位运算的能⼒,更⽅便了我们再⽇常代码中的使⽤。