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

[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. vue 快速入门 系列 —— 使用 vue-cli 3 搭建一个项目(下)

    其他章节请看: vue 快速入门 系列 使用 vue-cli 3 搭建一个项目(下) 上篇 我们已经成功引入 element-ui.axios.mock.iconfont.nprogress,本篇继续 ...

  2. OPPO 图数据库平台建设及业务落地

    本文首发于 OPPO 数智技术公众号,WeChat ID: OPPO_tech 1.什么是图数据库 图数据库(Graph database)是以图这种数据结构存储和查询的数据库.与其他数据库不同,关系 ...

  3. laravel DB 类库

    DB 类操作数据库    基本用法: DB::table('tableName'); 获取操作tableName 表        增加信息        对数据库中的某个表增加数据主要有两个函数可以 ...

  4. 那一天,我被Redis主从架构支配的恐惧

    面试官:要不你来讲讲你最近在看的点呗?可以拉出来一起讨论下(今天我也不知道要问什么) 候选者:最近在看「Redis」相关的内容 面试官:嗯,我记得已经问过Redis的基础和持久化了 面试官:要不你来讲 ...

  5. <C#任务导引教程>练习四

    //27,创建一个控制台应用程序,声明两个DateTime类型的变量dt,获取系统的当前日期时间,然后使用Format格式化进行规范using System;class Program{    sta ...

  6. mysql注入绕过information_schema过滤

    1.利用mysql5.7新增的sys.schema_auto_increment_columns 这是sys数据库下的一个视图,基础数据来自与information_schema,他的作用是对表的自增 ...

  7. YAPI接口自动鉴权功能部署详解

    安装准备 以下操作,默认要求自己部署过yapi,最好是部署过yapi二次开发环境. 无论是选择在线安装或者是本地安装,都需要安装client工具. 1.yapi-cli:npm install yap ...

  8. 《python编程从入门到实践》读书实践笔记(二)

    本文是<python编程从入门到实践>读书实践笔记11章的内容,主要包含测试,为体现测试的重要性,独立成文. 11 测试代码 写在前面的话,以下是我这些年开发中和测试相关的血泪史. 对于一 ...

  9. Redis队列跟MQ的区别

    Redis队列:Redis队列是一个Key-Value的NoSQL数据库,开发维护很活跃,虽然是一个Key-Value数据库存储系统,但它本身支持MQ功能,所以完全可以当做一个轻量级的队列服务来使用 ...

  10. 【数据库】本地NR数据库如何按物种拆分?

    目录 1.准备本地数据库文件 1.1 NR库下载 1.2 Taxonomy数据库下载 2.按物种拆分NR库 2.1 第一步:获得Aceesson和分类物种的对应关系 2.2 第二步:获得分类物种的序列 ...