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定义的准则:

  • 使用FlagsAttribute枚举才是对数字值执行按位运算 (AND、 OR 独占或) 的自定义属性。

  • 在 2 的幂,即 1、 2、 4、 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....)

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


[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/

原文:https://www.cnblogs.com/Wolfmanlq/p/8525090.html


.NET社区新闻,深度好文,欢迎访问公众号文章汇总 http://www.csharpkit.com

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/321986.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

重温.NET下Assembly的加载过程

最近在工作中牵涉到了.NET下的一个古老的问题:Assembly的加载过程。虽然网上有很多文章介绍这部分内容,很多文章也是很久以前就已经出现了,但阅读之后发现,并没能解决我的问题,有些点写的不是特别详细,让人…

看eShopOnContainers学一个EventBus

最近在看微软eShopOnContainers 项目,看到事件总线觉得不错,和大家分享一下看完此文你将获得什么?eShop中是如何设计事件总线的实现一个InMemory事件总线eShop中是没有InMemory实现的,这算是一个小小小的挑战发布订阅模式发布订阅…

创建基于MailKit和MimeKit的.NET基础邮件服务

邮件服务是一般的系统都会拥有和需要的功能,但是对于.NET项目来说,邮件服务的创建和使用会较为的麻烦。.NET对于邮件功能提供了System.Net.Mail用于创建邮件服务,该基础服务提供邮件的基础操作,并且使用也较为的简单。对于真正将该…

EF Core下利用Mysql进行数据存储在并发访问下的数据同步问题

小故事在开始讲这篇文章之前,我们来说一个小故事,纯素虚构(真实的存钱逻辑并非如此)小刘发工资后,赶忙拿着现金去银行,准备把钱存起来,而与此同时,小刘的老婆刘嫂知道小刘的品性&…

牛客练习赛50-记录

正题 比赛链接:https://ac.nowcoder.com/acm/contest/1080#question 成绩 本届 升高二届 总结 以后还是不要写太多自己不擅长的写法,空间要多检查,不要像个傻逼一样啥都写错。 尽量不要为了省一点空间和时间写一些不舒服的东西,尽量在能…

物联网框架ServerSuperIO在.NetCore实现跨平台的实践路线

正所谓天下大势,不跟风不行。你不跨平台,很low嘛。java说:你们能跨嘛,跨给我看看。C#说:不要强人所难嘛。java说:能部署在云上吗?docker?微服务?C#说:不要强人…

使用WebApiClient请求和管理Restful Api

前言本篇文章的内容是WebApiClient应用说明篇,如果你没有了解过WebApiClient,可以先阅读以下相关文章:WebApi client 的面向切面编程我来给.Net设计一款HttpClient.Net45下HttpClient的几个缺陷.net的retrofit--WebApiClient库.net的retrofit…

拥抱.NET Core系列:MemoryCache 缓存选项

MSCache项目MSCache 目前最新的正式版是 2.0.0,预览版是2.1.0,会与 .NETCore 2.1 一起发布。本篇用了2.0.0版本开源在 GitHub 上,仓库地址是:https://github.com/aspnet/CachingNuGet地址为:https://www.nuget.org/pac…

牛客练习赛51-记录

正题 比赛链接:https://ac.nowcoder.com/acm/contest/1083#question 成绩 可怜的zycT3zycT3zycT3被n0n0n0卡了半天,这里感谢一下排雷 总结 比赛状态较好,后面没有T6T6T6的题解 T1:abcT1:abcT1:abc 题目大意 给出一个字符串,求有多少个abc…

Metrics.net + influxdb + grafana 构建WebAPI的自动化监控和预警

前言这次主要分享通过Metrics.net influxdb grafana 构建WebAPI的自动化监控和预警方案。通过执行耗时,定位哪些接口拖累了服务的性能;通过请求频次,设置适当的限流和熔断机制,拦截非法或不合理的请求,保障服务的可用…

EF Core 2.1路线图:视图、GROUP BY和惰性加载

Entity Framework Core一直追随着初始Entity Framework的发展,并不断推陈出新。它首先推出的是对视图的支持,这听起来有些耸人听闻。在即将推出的EF Core 2.1之前,EF Core并未对数据库视图提供官方的支持,也不支持缺少主键的数据库…

计算机网络总结

一、计算机网络体系 (1)OSI分层 (7层) 物理层、数据链路层、网络层、传输层、会话层、表示层、应用层。 (2)TCP/IP分层(4层) 网络接口层、 网际层、运输层、 应用层。 &#xff0…

从技术角度讨论微服务

本文希望从技术角度来探讨下微服务,因此,不会过多地谈及如何根据业务进行微服务划分,更多是介绍微服务的相关技术,微服务的业务划分方法可参考“领域驱动设计“相关方法论。微服务的两个程度一、服务化复杂的单体架构会有以下的挑…

jzoj6344-[NOIP2019模拟2019.9.7]Huge Counting【组合数,状压dp】

正题 题目大意 定义函数f(x)(xf(x)(xf(x)(x为一个序列))) 若任意一个xi1x_i1xi​1那么有f(x)1f(x)1f(x)1 若有一个xi0x_i0xi​0那么有f(x)0f(x)0f(x)0 其他的,有f(x)(∑j1nf(x1...,xj−1,...xn))%2f(x)(\sum_{j1}^nf(x_{1}...,x_j-1,...x_n))\% 2f(x)(j1∑n​f(x1​…

拥抱.NET Core系列:MemoryCache 缓存域

MSCache项目MSCache 目前最新的正式版是 2.0.0,预览版是2.1.0,会与 .NETCore 2.1 一起发布。本篇用了2.0.0版本开源在 GitHub 上,仓库地址是:https://github.com/aspnet/CachingNuGet地址为:https://www.nuget.org/pac…

牛客小白月赛17-记录(附题解)

正题 比赛链接:https://ac.nowcoder.com/acm/contest/1085#question 成绩 总结 除了那道积分数学其他还好 后面没有FFF题的题解 T1:小sun的假期T1:小sun的假期T1:小sun的假期 题目大意 长度为nnn的序列,mmm个区间,求最大的没有被任何区间覆盖的区间…

安全、高效的MySQL DDL解决方案

MySQL作为目前应用最广泛的开源关系型数据库,是许多网站、应用和商业产品的主要数据存储。在生产环境,线上数据库常常面临着持续的、不断变化的表结构修改(DDL),如增加、更改、删除字段和索引等等。其中一些DDL操作在M…

DNS总结

一、DNS (1)简介 域名系统(英文:Domain Name System,缩写:DNS)是互联网的一项服务。它作为将域名和IP地址相互映射的一个分布式数据库,能够使人更方便地访问互联网。 DNS 协议也是…

谈谈在.NET Core中使用Redis和Memcached的序列化问题

前言在使用分布式缓存的时候,都不可避免的要做这样一步操作,将数据序列化后再存储到缓存中去。序列化这一操作,或许是显式的,或许是隐式的,这个取决于使用的package是否有帮我们做这样一件事。本文会拿在.NET Core环境…

牛客练习赛52-记录

正题 比赛链接:https://ac.nowcoder.com/acm/contest/1084#question 成绩 T1:T1:T1:数数 题目大意 给出nnn,求∑i1n∑j1n(i∗j)\sum_{i1}^n \sum_{j1}^n (i*j)i1∑n​j1∑n​(i∗j) 和 ∏i1n∏j1n(i∗j)\prod_{i1}^n\prod_{j1}^n(i*j)i1∏n​j1∏n​(i∗j) 解题…