【实用】超简单的基于枚举型使用1个字节表示8个权限的方法

前言

在进行权限管理时,有很多的权限属于布尔型权限,即只有“有”或“无”两种状态,在表示的时候只需要一个位(bit)。但是在基本类型中,最小的单元也是字节(byte),这样的话不仅造成很大的浪费,而且字段多了,也不便于管理。本文利用枚举型变量,使用基于位运行的策略,可以使用1个字节表示8个权限,从而解决了以上两个问题。本文同时附上C#和Java的实现。

位运行

本方法主要利用的是位运行 &|,通过两者的使用,可以分别进行 set 和 get 两种常见的操作。具体参见以下C#代码。

C#实现

static void Main()
{
    //    Permissions permissions = new Permissions();
    //    // 1.初始化权限变量 p
    //    Permission p = permissions.ParsePermission(0);
    //    permissions.ShowPermission(p);
    //    // 2.为 p 添加 Add 权限并显示
    //    p = permissions.SetPermission(p, Permission.Add, true);
    //    permissions.ShowPermission(p);
    //    // 3.为 p 添加 Edit 权限并显示
    //    p = permissions.SetPermission(p, Permission.Edit, true);
    //    permissions.ShowPermission(p);
    //    // 4.为 p 移除 Add 权限并显示
    //    p = permissions.SetPermission(p, Permission.Add, false);
    //    permissions.ShowPermission(p);
    //    // 5.为 p 添加 View 权限并显示
    //    p = permissions.SetPermission(p, Permission.View);
    //    permissions.ShowPermission(p);
    //    Console.WriteLine("转成整型:" + permissions.PermissionsToInt(p));
    //    Console.Read();

    // 获得权限集合,使用int型最多可以获得31位权限(取不到32位,因为int有正负,最大值为2^31)
    int a =  42442301;
    
    // 输出2位权限,对应的输出为 “10100001111001111000111101”
    Console.WriteLine(Convert.ToString(a, 2));
    
    // 从a解析权限
    Permissions p = (Permissions) Enum.Parse(typeof(Permissions), a.ToString());

    // 获得某2个权限并判断,返回结果为 True, False
    Console.WriteLine((p & Permissions.v0) == Permissions.v0);
    Console.WriteLine((p & Permissions.v1) == Permissions.v1); 
    
    // 显示全部有的权限, 输出如下:
    // Permissions granted: v0, v2, v3, v4, v5, v9, v10, v11, v12, v15, v16, v17, v18, v23, v25
    Console.Write("Permissions granted: ");
       foreach (Permissions item in Enum.GetValues(typeof(Permissions)))
           if ((p & item) == item)
               Console.Write(item + ", ");

    
    // 直接显示p,会转换为整型,输出为:42442301
    Console.WriteLine(p);
    
    // 设置权限
    p |= Permissions.v1;

    // 设置权限后结果为 True
    Console.WriteLine((p & Permissions.v1) == Permissions.v1);

    // 保存结果,此时输出为 42442303, 由于 v1(值为2)为 True,所以增加了2。
    a = (int)p;
    Console.WriteLine(a);
}
// 补充几点:
// 1. Permissions.v1.ToString() 返回 v1,即枚举的值的名称字符串
// 2. (int)Permissions.v1 返回 1
// 3. 从字符串解析出 Permission 可以使用 (Permission)Enum.Parse(typeof(Permission), “v1"); 
// 4. 如果字符串解析失败,出跳出异常,可以使用以下办法简化操作:
//    static Permission ParsePermission(string str){
//        try{
//            return (Permission)Enum.Parse(typeof(Permission), str);
//        }
//        catch { }
//        return Permission.None;
//    }

// 所有的值为 2^(i+1), 其中 i in [0, 30],共31位
// 在实际使用中,将v0, v1, ..., v30换成是对应的权限名称即可,如 Insert, Delete等等。
public enum Permissions:int
{
    None = -1,
    v0 = 1,
    v1 = 2,
    v2 = 4,
    v3 = 8,
    v4 = 16,
    v5 = 32,
    v6 = 64,
    v7 = 128,
    v8 = 256,
    v9 = 512,
    v10 = 1024,
    v11 = 2048,
    v12 = 4096,
    v13 = 8192,
    v14 = 16384,
    v15 = 32768,
    v16 = 65536,
    v17 = 131072,
    v18 = 262144,
    v19 = 524288,
    v20 = 1048576,
    v21 = 2097152,
    v22 = 4194304,
    v23 = 8388608,
    v24 = 16777216,
    v25 = 33554432,
    v26 = 67108864,
    v27 = 134217728,
    v28 = 268435456,
    v29 = 536870912,
    v30 = 1073741824
};

函数封装及应用

以下展示使用函数进行封装后的应用实例 。先看输出:

None
Add
Add | Edit
Edit
Edit | View
转成整型:6

以下是源代码 。

using System;
using System.Collections.Generic;
namespace ConsoleApp1
{
    public enum Permission:int 
    {
        None = 0,
        Add = 1,
        Edit = 2, 
        View = 4,
        Search = 8
    }
    
    class Program
    {
        static void Main(string[] args)
        {
            // 初始化权限变量 p
            Permission p = ParsePermission(0);
            ShowPermission(p);

            // 为 p 添加 Add 权限并显示
            p = SetPermission(p, Permission.Add, true);
            ShowPermission(p);

            // 为 p 添加 Edit 权限并显示
            p = SetPermission(p, Permission.Edit, true);
            ShowPermission(p);

            // 为 p 移除 Add 权限并显示
            p = SetPermission(p, Permission.Add, false);
            ShowPermission(p);


            // 为 p 添加 View 权限并显示
            p = SetPermission(p, Permission.View);
            ShowPermission(p);

            Console.WriteLine("转成整型:" + PermissionsToInt(p));
            Console.Read();
        }

        /// <summary>
        /// 显示权限P,如果有多个权限以|为分隔符进行显示。
        /// </summary>
        /// <param name="p"></param>
        private static void ShowPermission(Permission p)
        {
            int pi = 1;
            List<Permission> pms = new List<Permission>();
            for (int i = 0; i < 30; i++)
            {
                Permission p1 = ParsePermission(pi);
                if (HasPermission(p, p1))
                    pms.Add(p1);
                pi = pi << 1;
            }

            if (pms.Count == 0)
                pms.Add(Permission.None);

            Console.WriteLine(string.Join(" | ", pms));
        }

        /// <summary>
        /// 从一个整型变量解析出权限。
        /// </summary>
        /// <param name="p"></param>
        /// <returns></returns>
        public static Permission ParsePermission(int p)
        {
            return (Permission)Enum.Parse(typeof(Permission), p.ToString());
        }

        /// <summary>
        /// 判断给定的权限是否具有某个权限。
        /// </summary>
        /// <param name="original"></param>
        /// <param name="p"></param>
        /// <returns></returns>
        public static bool HasPermission(Permission original, Permission p)
        {
            return (original & p) == p;
        }

        /// <summary>
        /// 为给定的权限添加或去除某个权限。
        /// </summary>
        /// <param name="original"></param>
        /// <param name="p"></param>
        /// <param name="available"></param>
        /// <returns></returns>
        public static Permission SetPermission(Permission original, Permission p, bool available = true)
        {
            return available ? original | p : original & ~p;
        }

        /// <summary>
        /// 将指定的权限转成整型。
        /// </summary>
        /// <param name="original"></param>
        /// <returns></returns>
        public static int PermissionsToInt(Permission original)
        {
            return (int)original;
        }
    }
}

Java 实现

PS: 在Java中也一样可以用上面的方法,只不过Java的Enum类不提供相应的方法,需要自己实现。如果嫌麻烦,还有个更简单的办法,使用静态变量,代码如下所示,可以得到相似的结果。

public class Permissions {
	public final static	int INSERT = 1;
	public final static	int DELETE = 2;
	 
	public static void main(String[] args) {
		int p = 42442301;
		System.out.println((p & Permissions.INSERT) == Permissions.INSERT);
		System.out.println((p & Permissions.DELETE) == Permissions.DELETE); 
		p |= Permissions.DELETE;
		System.out.println((p & Permissions.DELETE) == Permissions.DELETE); 
		System.out.println(p);
	}
}	

以下是输出

true
false
true
42442303
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值