c# 二进制或算法实现枚举的HasFlag函数

from:http://www.cnblogs.com/icyJ/archive/2013/02/20/HasFlag.html

在权限的管理中,常常会出现一个权限包含的现象。例如,有三种基本权限:职员A、职员B、职员C.在此基础上,有经理权限,它包括A和B两种权限;还有老板权限,包含A/B/C三种权限。

在代码中,我们可以用枚举来管理这些权限。

[Flags]
public enum EnumHasFlag
{
    A = 1 << 0,
    B = 1 << 1,
    C = 1 << 2,
    Manager = A | B,
    Boss = A | B | C,
}

这段代码的特点是,定义枚举是用了一个属性来限制[Flags],以及每个值都是用二进制递增来赋值。这样做的好处是,可以通过枚举的HasFlag函数来判断某一个权限是否包含另一个权限。

static void Main(string[] args)
{
    var rightA = EnumHasFlag.Boss;
    var rightB = EnumHasFlag.Manager;
    if (rightA.HasFlag(EnumHasFlag.C)) Console.WriteLine("rightA can do this");
    if (rightB.HasFlag(EnumHasFlag.C)) Console.WriteLine("rightB can do this");
    Console.ReadKey();
}

最终代码会输出:rightA can do this。这样,通过HasFlag就可以判断枚举值的包含关系,从而进行相应的权限指定和管理。

这样的效果,还可以用过二进制的或运算来实现。基本语句是source | target == source.某个数值A,与另一个数值B进行或运算之后的结果还是A的话,可以判断A包含B。

static void Main(string[] args) {     
var A = 1 << 0 | 1 << 1;     
if ((A | (1 << 0)) == A) 
Console.WriteLine("A has 1<<0");     
if ((A | (1 << 2)) != A) 
Console.WriteLine("A doesn‘t have 1<<2"); }

代码的输出结果为:

A has 1<<0

A doesn‘t have 1<<2

在了解逻辑的前提下,我们可以做如下的开关:

static void Main(string[] args)
{
    ControlCenter(1 << 0 | 1 << 3);
}

static void ControlCenter(int input)
{
    if ((input | (1 << 0)) == input) Console.WriteLine("Do 0");
    if ((input | (1 << 1)) == input) Console.WriteLine("Do 1");
    if ((input | (1 << 2)) == input) Console.WriteLine("Do 2");
}

最终的输出结果可以自己下去测试一下。

本篇用两种方法来实现数值的包含关系管理。仔细的理解了实现的逻辑之后,可以用在很多地方。例如,我们可以将多个设置的是否值揉合成一个字段。形如‘10111101‘,用最少的代码来管理这些设置信息。在选项很少而且对象的活动领域很小的情况下,可以考虑用二进制的或运算来实现。这样实现的优点是,可以不用单独建立枚举,代码量少很多;缺点是,代码的可读性差,调用灵活度也不如枚举的HasFlag,可扩展性也不强。

补充。下面有园友提出了source & target == target的判断算法,来判断source是否包含target。我觉得条件非常充分,而且整个思路比或运算更加清晰。后来查阅了其他的资料,发现对枚举中的1,2,4,8的理解,很多都是从这个算式出发。


static void Main(string[] args){    var xx = TestEnum.Manager;    if ((xx & TestEnum.A) == TestEnum.A) Console.WriteLine("Has A");    Console.ReadKey();}

enum TestEnum{    A = 1 << 0,    B = 1 << 1,    C = 1 << 2,    Manager = A | B,    Boss = A | B | C,}
时间: 2024-07-31 10:26:07

c# 二进制或算法实现枚举的HasFlag函数的相关文章

十进制转二进制-快速算法

#include<iostream> #include<string> #include<algorithm> using namespace std; int main(int agrc, char *agrv[]) { int iInPut = 0; while (cin >> iInPut) { string sBinary;//转换后的二进制存储为字符串,调用了默认构造函数初试化为空串 int temp = abs(iInPut); if (temp

使用哈希算法将数字解析为函数指针-一种架构方法

使用哈希算法将数字解析为函数指针: 这也算是最简单的,不会带有地址冲突的哈希了,哈希函数可以描述为: func = arr[index].func index为输入,根据输入的index,找到其对应的函数指针返回 这种架构虽然简单,但是在做测试时还是非常有用的 比如一种测试有几十项,我可以使用这种架构来实现自动轮巡测试,或者手动交互时输入一个Index,即可以去调用对应的测试函数 另外根据这个代码,还可以学习到函数指针的定义和使用: 定义:typedef int (*FuncPtr)(char

算法6-1:哈希函数

在上章节中已经介绍了通过红黑树实现键值对数组的查询操作,复杂度是logN.有没有性能更好的算法呢?答案是有. 基本想法就是计算关键字的哈希值,再通过哈希值直接获取对应的键值. 这种方法的需要解决的问题是: 如何计算哈希值 如何解决哈系冲突 哈希函数 目标 根据对象中的成员变量的值,按照一定的规则计算出一个整数,这个整数就是哈希值. 哈希值最重要的两个属性是: 如果a.equals(b),那么a.hashCode() == b.hashCode() 理想状况下,如果!a.equals(b),那么a

枚举导出的函数

//枚举导出的函数 // #include <idc.idc> static main() { auto entrypoints,i,ord,addr,name,purged,file,fd; file = AskFile(1,"*.idt","Select IDT save file"); //打开文件对话框 fd = fopen(file,"w"); //以写的方式打开 entrypoints = GetEntryPointQty

编程算法 - 求1+2+...+n(函数继承) 代码(C++)

求1+2+...+n(函数继承) 代码(C++) 本文地址: http://blog.csdn.net/caroline_wendy 题目: 求1+2+...+n, 要求不能使用乘除法\for\while\if\else\switch\case等关键字及条件判断语句(A?B:C). 可以使用函数继承, 通过递归调用, 每次递归值减1, 使用求反运算(!), 即非0为0, 0为1. 代码: /* * main.cpp * * Created on: 2014.7.12 * Author: spik

编程算法 - 求1+2+...+n(函数指针) 代码(C++)

求1+2+...+n(函数指针) 代码(C++) 本文地址: http://blog.csdn.net/caroline_wendy 题目: 求1+2+...+n, 要求不能使用乘除法\for\while\if\else\switch\case等关键字及条件判断语句(A?B:C). 可以使用函数指针求解, 通过递归调用, 每次递归值减1, 使用求反运算(!), 即非0为0, 0为1. 代码: /* * main.cpp * * Created on: 2014.7.12 * Author: sp

python之枚举--内置函数-enumerate()

python之枚举 内置函数 enumearate() enumerate()是python的内置函数 enumerate在字典上是枚举.列举的意思 对于一个可迭代的(iterable)/可遍历的对象(如列表.字符串),enumerate将其组成一个索引序列,利用它可以同时获得索引和值 enumerate多用于在for循环中得到计数 enumerate()使用 如果对一个列表,既要遍历索引又要遍历元素时,首先可以这样写: list=["这","是","一个

算法学习 -- 枚举

在学习枚举算法之前,首先问有关枚举的几个问题 1. 为什么要进行枚举? 2. 需要对哪些对象进行枚举? 3. 如何进行枚举? 4. 枚举的结束条件是什么? 现在针对两个使用枚举算法的实例对以上问题进行分析. 实例一:熄灯问题 给定一个5×6的棋盘,上面有灯,每个灯都有各自的按钮,每个按钮按下去都会使其自己和周围的上下左右四盏灯改变(原来熄灭的变亮,原来亮的变灭),如何操作按钮使这个棋盘上所有灯都熄灭. 实例二:青蛙问题 一个5000×5000的稻田,有很多青蛙从这个稻田上跳过,每只青蛙跳过的步长

《啊哈算法》——枚举

枚举法,作为编程世界里一个非常基本的方法或者说技巧,它也可以叫穷举法.暴力法.遍历法,深入了解一些算法后,你会发现它在算法世界当中的用途非常的广泛. 概括地说这种方法非常的简单,我们抽象点来说,对于一个问题的解x,这个解满足限制条件f(x),枚举法给出解决问题的方案是一一列举x所有可能的情况,然后判断是否满足限制条件f(x),如果满足,则x是问题的解:反之,不是. 枚举法虽然简单,但是在解决实际问题中往往伴随着比较巧妙的优化与筛选,而且在枚举算啊中体现出的“找到x所有可能的情况”,在其他的一些算