服务器之家:专注于服务器技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - C# - C#中枚举的特性 FlagAttribute详解

C#中枚举的特性 FlagAttribute详解

2022-02-20 14:12KenWang C#

说到FlagsAttribute,源自前几天看到了一小段代码,大概意思就是根据航班政策来返回哪些配送方式是否可用,根据这些是否可用来隐藏或者开启界面的相关配送方式,不是非常明白,于是今天我们就来详细探讨下这个问题

写在前面

枚举Enum 全称(Enumeration),即一种由一组称为枚举数列表的命名常量组成的独特类型。可以看出枚举的出现时为了使我们可以在程序中方便的使用一些特定值的常量,一般的使用大家都比较熟悉,本文主要介绍枚举的特性 FlagAttribute。

FlagAttribute是什么?

Flag 特性微软的解释是:指示可以将枚举作为位域(即一组标志)处理,FlagsAttribute属性就是枚举类型的一项可选属性,它的主要作用是可以将枚举作为位域处理(P.S. C#不支持位域)。所谓位域是单个存储单元内相邻二进制位的集合。通过为枚举添加这个属性,可以改变枚举的一些行为来满足我们的需要。

比如我们有如下枚举的定义:

?
1
2
3
4
5
6
7
8
9
10
public enum OrderTypeEnum
{
  Init,
 
  Complete,
 
  Waiting,
 
  Paid
}

逻辑或操作我相信大家都比较熟悉了,对于整数来说,| 操作就是将其转化为二进制再进行或运算。OrderTypeEnum.Init | OrderTypeEnum.Complete做的工作实际上是 0001 | 0010 = 0011 = 3再转换成(OrderTypeEnum)3就是OrderTypeEnum.Paid了.

如果我们对两个枚举值做 | 操作,那结果会是什么样呢?

?
1
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....)

那我们重新看一下重新定义之后的或操作会是什么结果呢?

?
1
2
3
4
5
6
7
8
9
10
11
[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 ;

那么同理也可以来判断这样的集合中是否包含某个枚举值:

?
1
result.HasFlag(OrderTypeEnum.Paid)  

写在最后

枚举通过添加Flags的特性使得它能够拥有位运算的能力,更方便了我们再日常代码中的使用。

参考资料:http://www.alanzucconi.com/2015/07/26/enum-flags-and-bitwise-operators/

原文链接:http://www.cnblogs.com/Wolfmanlq/p/8525090.html

延伸 · 阅读

精彩推荐
  • C#SQLite在C#中的安装与操作技巧

    SQLite在C#中的安装与操作技巧

    SQLite,是一款轻型的数据库,用于本地的数据储存。其优点有很多,下面通过本文给大家介绍SQLite在C#中的安装与操作技巧,感兴趣的的朋友参考下吧...

    蓝曈魅11162022-01-20
  • C#三十分钟快速掌握C# 6.0知识点

    三十分钟快速掌握C# 6.0知识点

    这篇文章主要介绍了C# 6.0的相关知识点,文中介绍的非常详细,通过这篇文字可以让大家在三十分钟内快速的掌握C# 6.0,需要的朋友可以参考借鉴,下面来...

    雨夜潇湘8272021-12-28
  • C#VS2012 程序打包部署图文详解

    VS2012 程序打包部署图文详解

    VS2012虽然没有集成打包工具,但它为我们提供了下载的端口,需要我们手动安装一个插件InstallShield。网上有很多第三方的打包工具,但为什么偏要使用微软...

    张信秀7712021-12-15
  • C#深入理解C#的数组

    深入理解C#的数组

    本篇文章主要介绍了C#的数组,数组是一种数据结构,详细的介绍了数组的声明和访问等,有兴趣的可以了解一下。...

    佳园9492021-12-10
  • C#如何使用C#将Tensorflow训练的.pb文件用在生产环境详解

    如何使用C#将Tensorflow训练的.pb文件用在生产环境详解

    这篇文章主要给大家介绍了关于如何使用C#将Tensorflow训练的.pb文件用在生产环境的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考借鉴...

    bbird201811792022-03-05
  • C#C#设计模式之Strategy策略模式解决007大破密码危机问题示例

    C#设计模式之Strategy策略模式解决007大破密码危机问题示例

    这篇文章主要介绍了C#设计模式之Strategy策略模式解决007大破密码危机问题,简单描述了策略模式的定义并结合加密解密算法实例分析了C#策略模式的具体使用...

    GhostRider10972022-01-21
  • C#利用C#实现网络爬虫

    利用C#实现网络爬虫

    这篇文章主要介绍了利用C#实现网络爬虫,完整的介绍了C#实现网络爬虫详细过程,感兴趣的小伙伴们可以参考一下...

    C#教程网11852021-11-16
  • C#C#微信公众号与订阅号接口开发示例代码

    C#微信公众号与订阅号接口开发示例代码

    这篇文章主要介绍了C#微信公众号与订阅号接口开发示例代码,结合实例形式简单分析了C#针对微信接口的调用与处理技巧,需要的朋友可以参考下...

    smartsmile20127762021-11-25