C# 枚举的flags 标志位应用
枚举有个特性叫标志位,使用方法如下
[Flags]
enum Foo
{
a =1,
b = 2,
c = 4,
d = 8
}
每个值需要为2的n次方,保证多个值的组合不会重复.
这样在判断其中一个枚举值c 是否在a,b,c这个范围中就可以简化写法
常规写法如下
var c = Foo.c;
if( c == Foo.a || c == Foo.b || c == Foo.c )
{ }
因为值为2的n次方,所以可以通过按位相与来得出是否在范围内
var c = Foo.c;
if( (c & ( Foo.a | Foo.b | Foo.c ) != c )
{ }
注意,如果c在范围内则结果等于c,否则结果为0
可以写个扩展方法
public static class EnumExtension
{
/// <summary>
/// 判断该枚举是否在范围内 注意:该枚举类型需要有[Flags] 标注
/// </summary>
/// <param name="source">待比较的值</param>
/// <param name="range">枚举范围</param>
/// <returns></returns>
public static bool IsIn(this Enum source, params Enum[] range)
{
if(range.Length == 0)
{
return false;
}
else if(range.Length == 1)
{
return source == range[0];
}
int r = Convert.ToInt32(range[0]);
for (int i = 1; i < range.Length; i++)
{
r |= Convert.ToInt32(range[i]);
}
return !((Convert.ToInt32(source) & r) == 0);//也可写作return (Convert.ToInt32(source) & r) == Convert.ToInt32(source);
}
}
注意:不建议在EF的linq查询中调用扩展方法,可能会导致查询变为客户端评估,使得所有数据是查询全表后在内存中过滤,效率会低很多
调用如下
var c = Foo.c;
if(c.IsIn(Foo.a, Foo.b, Foo.c))
{
}
//如果判断单个枚举,则有官方提供的方法HasFlag
if(c.HasFlag(Foo.a))
{
}
拆分枚举
public static List<T> SplitEnum<T>(this T e) where T : Enum
{
var result = new List<T>();
foreach (T item in Enum.GetValues(typeof(T)))
{
if ((Convert.ToInt32(item) & Convert.ToInt32(e)) > 0)
{
result.Add(item);
}
}
return result;
}
合并枚举
public static T MergeEnum<T>(this IEnumerable<T> enums) where T : Enum
{
var enumValue = 0;
foreach (T item in enums)
{
enumValue |= Convert.ToInt32(item);
}
return (T)enumValue;
}
此外flags还会重写该枚举的ToString()
比如 由于3 = 1 | 2,所以3就相当于a|b
当对3强转为Foo后进行ToString会输出 a,b 而不是3

这样简单组合就可以得到新的有效枚举值,这种设计在权限等方面应用很多.
比如linux的文件权限 read write execute,缩写为r w x,对应值为 4 2 1
当需要一个值为
可读可写, r w, 4 | 2 = 6
可写可执行, w x, 2 | 1 = 3
可读可执行, r x, 4 | 1 = 5
可读可写可执行 r w x, 4 | 2 | 1 = 7
当然,也可以加上命名指定枚举值组合,比如定义一个ac 来替代a|c
[Flags]
enum Foo
{
a = 1,
b = 2,
c = 4,
ac = a | c,
d = 8
}
C# 枚举的flags 标志位应用的更多相关文章
- python正则表达式模块re:正则表达式常用字符、常用可选标志位、group与groups、match、search、sub、split,findall、compile、特殊字符转义
本文内容: 正则表达式常用字符. 常用可选标志位. group与groups. match. search. sub. split findall. compile 特殊字符转义 一些现实例子 首发时 ...
- Python正则表达式 re.sub()函数:标志位flags与参数个数问题
这两天在写爬虫程序,涉及英文文本处理,需要规范化英文标点符号的写法.正常情况下,英文句号「.」后面需要保证有且只有一个空格,但也有例外情况,比如「i.e.」.「e.g.」.「P.S.」这种.由于无法预 ...
- TCP/IP 标志位 SYN ACK RST UTG PSH FIN
三次握手:发送端发送一个SYN=1,ACK=0标志的数据包给接收端,请求进行连接,这是第一次握手:接收端收到请求并且允许连接的话,就会发送一个 SYN=1,ACK=1标志的数据包给发送端,告诉它,可以 ...
- 小冷-wireshark的标志位的值是啥
小冷系列之 wireshark的标志位的值是啥,在用wireshark抓包时,发现Flags = 0x002(SYN),很好奇0x002是什么意思. 好不好先上图: 上图是一个三次握手第一次的标志位, ...
- 进程保护--CrossThreadFlags标志位
原理: 1. 将进程的所有线程的线程CrossThreadFlags标志位设置成Terminated或者System. 效果:任务管理器,WSYSCheck,ICESWORD无法结束进程.. 但PCH ...
- [apue] 一个查看当前终端标志位设置的小工具
话不多说,先看运行效果: >./term input flag 0x00000500 BRKINT not in ICRNL IGNBRK not in IGNCR not in IGNPAR ...
- Java学习笔记14---使用标志位控制循环
使用标志位控制循环 前面提到了控制循环的常用技术:计数器控制的循环.另一种控制循环的常用技术是在读取和处理一个集合的值时指派一个特殊值.这个特殊的输入值也成为标志值(sentinel value),用 ...
- 汇编语言标志位 含义 NV UP EI NG NZ AC PE CY
缩写原意: Overflow of = OV NV [No Overflow] Direction df = DN (decrement) UP (increment) Interrupt if = ...
- STM32 串口固件库中定义的几个中断标志位什么意思?
在stm32f10x_usart.h中以上几个宏,很没有规律,诈一看还真不知道为什么会这么定义,其实通过代码就很容易明白: D7~D5:代表中断标志位对应的中断使能位在 CR1.CR2还是CR3寄存器 ...
随机推荐
- 『学了就忘』Linux软件包管理 — 40、Linux系统软件包介绍
目录 1.Linux系统软件包分类 2.源码包说明 3.二进制包说明 4.RPM包的优缺点 4.RPM包的两种安装方法 5.总结 1.Linux系统软件包分类 Linux系统下的软件包只有源码包和二进 ...
- Django 小实例S1 简易学生选课管理系统 0 初步介绍与演示
Django 小实例S1 简易学生选课管理系统 第0章--初步介绍与演示 点击查看教程总目录 作者自我介绍:b站小UP主,时常直播编程+红警三,python1对1辅导老师. 1 初步介绍 先介绍下这个 ...
- Exploring Matrix
import java.util.Scanner; public class J714 { /** * @taking input from user */ public static void ma ...
- 大厂技术实现 | 腾讯信息流推荐排序中的并联双塔CTR结构 @推荐与计算广告系列
作者:韩信子@ShowMeAI,Joan@腾讯 地址:http://www.showmeai.tech/article-detail/tencent-ctr 声明:版权所有,转载请联系平台与作者并注明 ...
- Kubernetes Pod 全面知识
Pod 是在 Kubernetes 中创建和管理的.最小的可部署的计算单元,是最重要的对象之一.一个 Pod 中包含一个或多个容器,这些容器在 Pod 中能够共享网络.存储等环境. 学习 Kubern ...
- 联盛德 HLK-W806 (四): 软件SPI和硬件SPI驱动ST7735液晶LCD
目录 联盛德 HLK-W806 (一): Ubuntu20.04下的开发环境配置, 编译和烧录说明 联盛德 HLK-W806 (二): Win10下的开发环境配置, 编译和烧录说明 联盛德 HLK-W ...
- [Noip 2018][标题统计 龙湖斗 摆渡车 对称二叉树]普及组题解
啊喂,都已经9102年了,你还在想去年? 这里是一个Noip2018年PJ第二题打爆的OIer,错失省一 但经过了一年,我学到了很多,也有了很多朋友,水平也提高了很多,现在回看当时: 今年的Noip ...
- do{...}while(0)的用法
零.导引第一次见到 do{...}while(0)是在学习libevent的时候,看到里面有很多类似#define TT_URI(want) do { \ char *ret = evhttp_uri ...
- centos 7的命令变化
1.service -> systemctl命令 2.ifconfig -> ip 命令 3.netstat -> ss命令 4.route -> ip route命令 5.t ...
- 【题解】洛谷P1001 A+B Problem
第一篇博客,献给2020年的残夏. 静听8月的热情与安宁,在竞赛中的时光如白驹过隙. 也不惧未知的风雨,努力向着既往的通途. 题目地址 https://www.luogu.com.cn/problem ...