枚举有个特性叫标志位,使用方法如下

[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 标志位应用的更多相关文章

  1. python正则表达式模块re:正则表达式常用字符、常用可选标志位、group与groups、match、search、sub、split,findall、compile、特殊字符转义

    本文内容: 正则表达式常用字符. 常用可选标志位. group与groups. match. search. sub. split findall. compile 特殊字符转义 一些现实例子 首发时 ...

  2. Python正则表达式 re.sub()函数:标志位flags与参数个数问题

    这两天在写爬虫程序,涉及英文文本处理,需要规范化英文标点符号的写法.正常情况下,英文句号「.」后面需要保证有且只有一个空格,但也有例外情况,比如「i.e.」.「e.g.」.「P.S.」这种.由于无法预 ...

  3. TCP/IP 标志位 SYN ACK RST UTG PSH FIN

    三次握手:发送端发送一个SYN=1,ACK=0标志的数据包给接收端,请求进行连接,这是第一次握手:接收端收到请求并且允许连接的话,就会发送一个 SYN=1,ACK=1标志的数据包给发送端,告诉它,可以 ...

  4. 小冷-wireshark的标志位的值是啥

    小冷系列之 wireshark的标志位的值是啥,在用wireshark抓包时,发现Flags = 0x002(SYN),很好奇0x002是什么意思. 好不好先上图: 上图是一个三次握手第一次的标志位, ...

  5. 进程保护--CrossThreadFlags标志位

    原理: 1. 将进程的所有线程的线程CrossThreadFlags标志位设置成Terminated或者System. 效果:任务管理器,WSYSCheck,ICESWORD无法结束进程.. 但PCH ...

  6. [apue] 一个查看当前终端标志位设置的小工具

    话不多说,先看运行效果: >./term input flag 0x00000500 BRKINT not in ICRNL IGNBRK not in IGNCR not in IGNPAR ...

  7. Java学习笔记14---使用标志位控制循环

    使用标志位控制循环 前面提到了控制循环的常用技术:计数器控制的循环.另一种控制循环的常用技术是在读取和处理一个集合的值时指派一个特殊值.这个特殊的输入值也成为标志值(sentinel value),用 ...

  8. 汇编语言标志位 含义 NV UP EI NG NZ AC PE CY

    缩写原意: Overflow of = OV NV [No Overflow] Direction df = DN (decrement) UP (increment) Interrupt if = ...

  9. STM32 串口固件库中定义的几个中断标志位什么意思?

    在stm32f10x_usart.h中以上几个宏,很没有规律,诈一看还真不知道为什么会这么定义,其实通过代码就很容易明白: D7~D5:代表中断标志位对应的中断使能位在 CR1.CR2还是CR3寄存器 ...

随机推荐

  1. Ubuntu系统下《汇编语言》环境配置

    说明 1.系统:Ubuntu codists@pc:~$ lsb_release -a No LSB modules are available. Distributor ID: Ubuntu Des ...

  2. dart系列之:dart类中的泛型

    目录 简介 为什么要用泛型 怎么使用泛型 类型擦除 泛型的继承 泛型方法 总结 简介 熟悉JAVA的朋友可能知道,JAVA在8中引入了泛型的概念.什么是泛型呢?泛型就是一种通用的类型格式,一般用在集合 ...

  3. [atARC075F]Mirrored

    假设$n=\sum_{i=0}^{k}a_{i}10^{i}$(其中$a_{k}>0$),则有$d=f(n)-n=\sum_{i=0}^{k}(10^{k-i}-10^{i})a_{i}$,考虑 ...

  4. 构建“元宇宙”,有哪些3D建模方式?

    "沉浸.3D世界.虚拟社交.虚拟购物",最近"元宇宙"的概念特别火.人们畅想通过AR/VR以及其他互联网技术,把现实世界的楼房街道.天气温度.人际关系等投射到虚 ...

  5. 【树莓派】Python开发工控机急停设计

    背景 我们在一些工业产品中使用树莓派替代了PLC和上位机,并借助树莓派的算力将AI和机器视觉引入工业领域. 以前的产品都不存在动作机构,仅仅将结果输出到指示灯.蜂鸣器或者显示器上,没有安全隐患, 现在 ...

  6. Codeforces 917D - Stranger Trees(矩阵树定理/推式子+组合意义)

    Codeforces 题目传送门 & 洛谷题目传送门 刚好看到 wjz 在做这题,心想这题之前好像省选前做过,当时觉得是道挺不错的题,为啥没写题解呢?于是就过来补了,由此可见我真是个大鸽子(( ...

  7. Contest 2050 and Codeforces Round #718 (Div. 1 + Div. 2) 题解

    竟然上 GM 了,incredible( A 首先如果 \(2050\nmid n\) 那显然就 \(-1\) 了,否则答案显然为 \(\dfrac{n}{2050}\) 的各位数字和. B 显然这个 ...

  8. R shiny 小工具Windows本地打包部署

    目录 服务器部署简介 windows打包部署 1. 部署基本框架 2.安装shiny脚本需要的依赖包 3.创建运行shiny的程序 [报错解决]无法定位程序输入点EXTPTE_PTR于动态链接库 将小 ...

  9. keyboard-interactive authentication with the ssh2 server failed 的SecureCRT报错解决

    两种解决方法: 一.选定SSH2,选择Authentication,勾选Password,然后将该选项上移,挪到第一位即可 或者: 二.服务器端修改配置 默认情况/etc/ssh/sshd_confi ...

  10. 使用 JDBC 驱动程序

    本部分提供使用 Microsoft JDBC Driver for SQL Server 与 SQL Server 数据库建立简单连接的快速入门指导.在连接到 SQL Server 数据库之前,必须首 ...