在权限的管理中,常常会出现一个权限包含的现象。例如,有三种基本权限:职员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,
}

15.6.6补充:

用linq to ef做hasflag查询时,做了一个测试,结果很有趣:

var f1 = db.Where(x => !x.Status.HasFlag(FlagEnum.Deleted));
var f2 = db.Where(x => ((int)x.Status & (int)FlagEnum.Deleted) != (int)FlagEnum.Deleted);
var f3 = db.Where(x => x.Status.HasFlag(FlagEnum.Deleted));
var f4 = db.Where(x => ((int)x.Status & (int)FlagEnum.Deleted) == (int)FlagEnum.Deleted);

对应的sql语句的where条件是:

f1

WHERE  NOT (((( CAST( [Extent1].[Status] AS int)) & ( CAST( 4 AS int))) =  CAST( 4 AS int)) AND ((CASE WHEN (( CAST( [Extent1].[Status] AS int)) & ( CAST( 4 AS int)) IS NULL) THEN cast(1 as bit) ELSE cast(0 as bit) END) = 0))

f2

WHERE  NOT ((4 = (( CAST( [Extent1].[Status] AS int)) & (4))) AND (( CAST( [Extent1].[Status] AS int)) & (4) IS NOT NULL))

f3

WHERE (( CAST( [Extent1].[Status] AS int)) & ( CAST( 4 AS int))) =  CAST( 4 AS int)

f4

WHERE 4 = (( CAST( [Extent1].[Status] AS int)) & (4))}

直接说明了HasFlag和source & target = target的关系。

欢迎纠正和补充。转载请注明出处:http://www.cnblogs.com/icyJ/

转载于:https://www.cnblogs.com/icyJ/archive/2013/02/20/HasFlag.html

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

  1. OPJ2.1基本算法之枚举1815:画家问题

    OPJ2.1基本算法之枚举 1815:画家问题 题目传送门 描述 有一个正方形的墙,由N*N个正方形的砖组成,其中一些砖是白色的,另外一些砖是黄色的.Bob是个画家,想把全部的砖都涂成黄色.但他的画笔 ...

  2. 1.Python算法之枚举算法

    1.什么是枚举算法?  枚举算法也叫穷举算法,最大特点是在面对任何情况时会尝试每一种解决方法.在进行归纳推力时,如果逐个考察了某类事件的所有可能情况,因而得出一般结论,那么这个结论是可靠的,这种归纳方 ...

  3. JavaScript实现floatAsBinaryString浮点转为二进制字符串算法(附完整源码)

    JavaScript实现floatAsBinaryString浮点转为二进制字符串算法(附完整源码) floatAsBinaryString.js完整源代码 floatAsBinaryString.j ...

  4. 2.1基本算法之枚举_1812完美立方

    http://noi.openjudge.cn/ch0201/1812/ C++代码来源于以下链接 https://blog.csdn.net/qq_26919935/article/details/ ...

  5. Openjudge_ 2.1基本算法之枚举_1809 两倍 C++ scratch

    http://noi.openjudge.cn/ch0201/solution/21246662/ /* Openjudge_ 2.1基本算法之枚举_1809 两倍 http://noi.openju ...

  6. 2.1基本算法之枚举_1749数字方格

    http://noi.openjudge.cn/ch0201/1749/ /* 2.1基本算法之枚举_1749数字方格01 http://noi.openjudge.cn/ch0201/1749/ht ...

  7. 【0-1背包】二进制灰狼算法解决0-1背包问题【Matlab】

    提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 一.0-1背包问题 1.问题描述 2.数学模型 二 .二进制灰狼算法 1.引言 2.算法改进 3.数学模型 4.算法流程 三 ...

  8. OPJ2.1基本算法之枚举7217:猴子吃桃

    OPJ2.1基本算法之枚举&&7217:猴子吃桃 题目传送门 思路:就是一个脑筋急转弯--(话说这一章有好多脑筋急转弯问题--) 因为每次分的时候,都会多出来一个,对于N个猴子,如果给 ...

  9. OPJ 2.1基本算法之枚举:熄灯问题

    OPJ 2.1基本算法之枚举 1813:熄灯问题 题目传送门 个人认为这是这一章为数不多不水的题之一--可能是我太弱了 思路: 既然这道题是枚举"算法"里的,那肯定就是要枚举.那么 ...

最新文章

  1. 衡量计算机的平均无故障时间6,平均无故障时间MTBF测试及计算过程
  2. kotlin访问控制符可见性
  3. java构造函数_JAVA的构造函数是怎么写的。万分感谢。路过的请不要嘲笑%_%
  4. 数论 —— 斐波那契数列(Fibonacci)
  5. JS中的立即执行函数
  6. ‘utf-8‘ codec can‘t decode byte 0xb8 in position 0: invalid start byte
  7. 东大OJ-1391-Big big Power
  8. Lua中ipairs和pairs的区别详解
  9. 因为马云,这也许是他们过得最有意思的腊八节
  10. android 时间水印相机,水印相机时间打卡
  11. Git遇到的问题:This is not a valid source path/URL
  12. 如何用RIGOL任意函数发生器产生任意波形
  13. matlab 光平面标定代码,光平面标定法
  14. 最小生成树的第三种求法-Borůvka (Sollin) 算法
  15. QT 调试时出现 Unable to create a debugging engine.
  16. Linux 文件后面带星号
  17. 硅谷的政治泡沫:反对特朗普,与美国大部分地区观念出现割裂
  18. js获取时间,根据时间生成数字
  19. 使用ANSI控制字体颜色
  20. 基于DYDX闪电贷在Cofix和Uniswap之间套利

热门文章

  1. 如何评价百度造车?字很少,事很大
  2. 新款iPhone,比绿更绿
  3. 马云养的蚂蚁赚钱如印钞:每小时盈利500万,程序员平均年薪竟没到百万
  4. 量子位MEET大会报名开启!各领域头部玩家集结,AI年度榜单揭晓,在这里预见智能科技新未来...
  5. 快速学习正则表达式,不用死记硬背,这里有份中文资源和互动学习网站
  6. Oracle在linux下使用小技巧
  7. H3C V7平台下的IRF堆叠
  8. ViewBag对象的更改
  9. Hystrix概述(二)
  10. activemq高级客户端选项