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寄存器 ...
随机推荐
- C语言二分查找法
参考了C语言中折半查找法(二分法)的实现 二分查找算法(C语言实现) 先附上代码 #include<stdio.h> int BinSearch(int arr[],int len,int ...
- C 语言基础,来喽!
前言 C 语言是一门抽象的.面向过程的语言,C 语言广泛应用于底层开发,C 语言在计算机体系中占据着不可替代的作用,可以说 C 语言是编程的基础,也就是说,不管你学习任何语言,都应该把 C 语言放在首 ...
- Python介绍和安装
python介绍和安装 目录 python介绍和安装 1. Python简介 2. 解释器 2.1 Python解释器的种类 2.2 Python解释器版本 3. Windows下安装Python 3 ...
- 保姆级别的vue + ElementUI 搭建后台管理系统教程
vue + ElementUI 搭建后台管理系统记录 本文档记录了该系统从零配置的完整过程 项目源码请访问:https://gitee.com/szxio/vue2Admin,如果感觉对你有帮助,请点 ...
- [loj2478]林克卡特树
原题等价于选择恰好$k+1$条不相交(无公共点)的路径使得边权和最大 证明:对于原题中的最优解,一定包含了k条0边权的边(否则可以将未使用的边删掉,然后将这条路径的末尾与不在同一个连通块内的点连边), ...
- littlevgl架构浅析
一. littlevgl有几个线程,作用是什么? 三个,主线程一个,和在主线程的hal_init函数中创建的另两个sdl线程. 主线程完成一系列初始化工作后,循环每10ms调用在lv_init函数 ...
- 『学了就忘』Linux用户管理 — 52、用户组管理相关命令
目录 1.添加用户组 2.删除用户组 3.把用户添加进组或从组中删除 4.有效组(了解) 1.添加用户组 添加用户组的命令是groupadd. 命令格式如下: [root@localhost ~]# ...
- nginx得请求转发代码-将请求转发到网关
首先:本地主机host更改成 192.168.111.1 gulimail.com 这样一访问网址就能映射到本地. 然后修改nginx得conf worker_processes 1; events ...
- IT公司都不喜欢招培训班出来的学生,那培训班的意义何在呢?
我一方面做过培训学校的老师,现在上班之余,还在培训学校做兼职老师,另一方面做过大厂和外求的技术面试官,主要是java方向的,应该对这个话题有充分的话语权. 在本文里,就从培训班的作用. ...
- Codeforces 1383E - Strange Operation(线段树优化 DP or 单调栈+DP)
Codeforces 题目传送门 & 洛谷题目传送门 Yet another 自己搞出来的难度 \(\ge 2800\) 的题 介绍一个奇奇怪怪的 \(n\log n\) 的做法.首先特判掉字 ...