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寄存器 ...
随机推荐
- Spring Boot中如何自定义starter?
Spring Boot starter 我们知道Spring Boot大大简化了项目初始搭建以及开发过程,而这些都是通过Spring Boot提供的starter来完成的.品达通用权限系统就是基于Sp ...
- [gym102798F]Skeleton Dynamization
考虑对于第$i$层$x$与第$i+1$层所对应的点$y$,点$p$在前$i$层中当且仅当$p$到$x$比$p$到$y$距离小 由此,考虑枚举第一层的一个点以及对应到第二层的边,通过bfs就可以确定第一 ...
- 构建“元宇宙”,有哪些3D建模方式?
"沉浸.3D世界.虚拟社交.虚拟购物",最近"元宇宙"的概念特别火.人们畅想通过AR/VR以及其他互联网技术,把现实世界的楼房街道.天气温度.人际关系等投射到虚 ...
- springboot项目中常遇到的问题-初学者最容易犯的错
1.在spring中有两个main方法 2.在idea中少提代码类了,或者某类中代码依赖关系没解决掉
- vue文件引入
<template> <div class="hello"> <h1>{{ msg }}</h1> <!-- <h1&g ...
- 随笔:关于.net core单文件AOT编译
.Net Core单文件发布已经很流畅了(vs已支持图形化操作发布). 但类似Go或者Graalvm JDK的完全事前编译为本地机器码的红能功能,还未发布于.net 6特性中,还处于实验室中. 另外, ...
- 在Ubuntu上安装Docker Engine
在Ubuntu上安装Docker Engine 这篇文章是介绍如何在在Ubuntu上安装Docker Engine,就是Google翻译官方文档的版本,英语好的直接官方原文.原文 要在Ubuntu上开 ...
- CF187D BRT Contract
考虑如果哪次经过了红灯则显然已经和出发的时间没关系了. 然后我们需要做的是怎么样找到最近的一个是红灯的点. 然后实际下是我们做一个前缀和:\(L_i = \sum d_i\) 然后求\(\min (L ...
- [GZOI2017]配对统计
发现我们可以在\(O(n)\)里很多处理出至多\(2n\)对好对. 然后转化成二维偏序. 然后想怎么做怎么做:排序+BIT,莫队都行.
- Codeforces 356E - Xenia and String Problem(哈希)
Codeforces 题面传送门 & 洛谷题面传送门 首先显然一个 gray 串的长度只可能是 \(2^k-1\),其中 \(k\in\mathbb{Z}\). 考虑将一个字符改成另外一个字符 ...