枚举类型表示组合状态的抽象代数原理
可以使用枚举类型定义位标志,从而使该枚举类型的实例可以存储枚举数列表中定义的值的任意组合。 (当然,某些组合在您的程序代码中可能没有意义或不允许使用。)
创建位标志枚举的方法是应用 System.FlagsAttribute 特性并适当定义一些值,以便可以对这些值执行 AND、OR、NOT 和 XOR 按位运算。 在位标志枚举中包含一个值为零(表示“未设置任何标志”)的命名常量。如果零值不表示“未设置任何标志”,则请不要为标志指定零值。
首先我们定义一个支持组合状态的枚举如下,用FlagsAttribute对定义的枚举类型进行标识:
[Flags] public enum Permission { None=0,
Create=1, Retrive=2, Update=4, Delete=8, All=Create|Retrive|Update|Delete, }
FlagsAttribute标签的意义是按照位域来处理此枚举类型:
/// <summary>Indicates that an enumeration can be treated as a bit field; that is, a set of flags.</summary> /// <filterpriority>1</filterpriority> [AttributeUsage(AttributeTargets.Enum, Inherited = false), ComVisible(true)] [Serializable] public class FlagsAttribute : Attribute { }
通常我们对组合的枚举类型的操作为:
1.检查组合中是否包含某个值 2.往组合中添加一个值 3.从组合中去掉某个值
我们定义上面三种操作如下:
public static class PermissionExtention { public static bool HasPermission(this Permission compositePermission, Permission verifiedPermission) { return (compositePermission & verifiedPermission) == verifiedPermission; } public static Permission AddPermission(this Permission compositePermission, Permission toAddPermission) { if (compositePermission.HasPermission(toAddPermission)) return compositePermission; else return compositePermission | toAddPermission; } public static Permission RemovePermission(this Permission compositePermission, Permission toRemovePermission) { //if (!compositePermission.HasPermission(toAddPermission)) // return compositePermission; //else return compositePermission & (~toRemovePermission); } public static Permission RemovePermission2(this Permission compositePermission, Permission toRemovePermission) { if (!compositePermission.HasPermission(toRemovePermission)) return compositePermission; else return compositePermission^toRemovePermission; } }
我们注意到我们使用了全部四种操作符:& ,|,^,~来是想上面的三种目的。直观上理解三个操作符的意义就是
x & y 整型按位“与”
x ^ y 整型按位“异或”
x | y 整型按位“或”
~x按位求反
RemovePermission 与 RemovePermission2 这两个方法需要说明一下,其中RemovePermission形式比较简单,一句代码搞定
compositePermission & (~toRemovePermission);
对待删除的元素按位取反之后,按位与,直接表示保留除了toRemovePermission之外的其它所有权限。
RemovePermission2形式更加好理解,但是容易出错。如果没有第一句的判断直接异或操作的话可能会把原来没有的权限加进去。
数学原理:抽象代数之二进制码词群
设w=a1a2...an是一个n位二进制数码,称为一个码词,S是所有这样的码词构成的集合,即S={a1a2...an|ai=0或1,i=1,2,...n}
在S中定义二元运算|,表示位运算按位或
所以我们把原来的枚举类型换成数学符号如下
None=0000,Create=0001,Retrive=0010,Update=0100,Delete=1000,All=1111
由四位二进制数组成的二进制码集合为S={a1a2a3a4|ai=0或1},即所有的可能权限组合组成此集合。
对于我们定义的运算|,显然在此集合上满足封闭性,结合律,另外单位元为None=0000
同时所有元素的逆元也为None=0000。
所以集合S构成一个群(S,|),并且满足交换律,所以也是Abel群。
并且最小生成元集为M={None=0000,Create=0001,Retrive=0010,Update=0100,Delete=1000}
所以所有的权限组合均可以由M中的元素生成。
下面来分析下前面代码中的各种运算符的数学集合意义,a表示一个二进制码词:
~: 表面上是求元素a的的按位求反,实际在集合中的意义是除去a元素的的其它所有元素的集合。
&: 按位与运算,在集合中的a&b的意义就是求a中的权限与b中权限的交集
^: 异或“^”运算相当于 a^b 相当于{权限x|x属于a,但x不属于b}U{权限y|y属于b,但不属于a}
|: 或运算“|”,在这里相当于是并运算,即集合得合并运算。
再回头看代码:
取得权限的交集,判断权限中是否包含verifiedPermission
public static bool HasPermission(this Permission compositePermission, Permission verifiedPermission) { return (compositePermission & verifiedPermission) == verifiedPermission; }
添加权限,取集合的合并结果
public static Permission AddPermission(this Permission compositePermission, Permission toAddPermission) { if (compositePermission.HasPermission(toAddPermission)) return compositePermission; else return compositePermission | toAddPermission; }
删除一个权限,原权限集合与集合(~toRemovePermission)的交集,其中(~toRemovePermission)这个集合表示toRemovePermission的补集。
public static Permission RemovePermission(this Permission compositePermission, Permission toRemovePermission) { //if (!compositePermission.HasPermission(toAddPermission)) // return compositePermission; //else return compositePermission & (~toRemovePermission); }
删除一个权限第二种方法.其中else之后的语句表示一个并集:{权限x|x属于compositePermission,但x不属于toRemovePermission}U{权限y|y属于toRemovePermission,但不属于compositePermission}
public static Permission RemovePermission2(this Permission compositePermission, Permission toRemovePermission) { if (!compositePermission.HasPermission(toRemovePermission)) return compositePermission; else return compositePermission^toRemovePermission; }
我们可以用枚举类型的此种用法实现程序中的状态组合,任务状态组合,权限管理组合等。
作者:Andy Zeng
欢迎任何形式的转载,但请务必注明出处。