C#中的位操作


   比较基础的东西,平时用的不多,真到碰到时却不会用了,下面是整理的一些资料

 int类型即Int32, 由4个字节32位表示,高第31位(编号从零开始)用来表示正负,1为负数,0为正数 (左表示高位,右表示低)
 int 类型的负数是采用补码来表示的,即在对应的int类型正数上按位求反后再加1
 比方计算-1,其正数为 0000000...001(31个零跟一个1) 那么按位求反后应该是 111111111....10 ,再加1的结果是11111111...111(32个1).

 long类型跟int类似,只不过long由8字节64位表示
 
 数据转换常用代码
//将16进制数0XFFFFFFFF转换为整数(Int32)
MessageBox.Show( Convert.ToInt32("FFFFFFFF", 16).ToString()); //显示 -1
//将2进制数11111111转换为整数(Int32),注意11111111 等效于 0000...00011111111 (前面24个零)
MessageBox.Show(Convert.ToInt32("11111111",2).ToString());// 显示 255

//将整数-1转换成2进制字符串
MessageBox.Show(Convert.ToString(-1, 2)); // -1的二进制表示,显示11111....11 (32个1)
//将整数-1转换成16进制字符串
MessageBox.Show(Convert.ToString(-1, 16)); // -1的16进制表示,显示FFFFFFFF

 使用BitConverter
   byte[] bytes = new byte[] { 0xFF, 0xFF, 0xFF, 0xFF,0 ,0};
   //取bytes数据的第0个到第3个元素(int类型有4个字节) ,转化成整数
   MessageBox.Show( BitConverter.ToInt32(bytes, 0).ToString()); //显示 -1;
  //将byte[] 数组表示成十六进制字符串序列,各元素转化后用 "-"连接,顺序不变
   MessageBox.Show( BitConverter.ToString(bytes)); //显示 FF-FF-FF-FF-0-0
 //获取10(Int32)的字节数组
 byte[] arr=BitConverter.GetBytes(10); //生成的数组为 {10,0,0,0} 
 MessageBox.Show(BintConverter.ToString(arr)); //显示为0A-0-0-0;
 这里注意10的Int32内存表示方法是 00-00-00-0A(高字节左边低字节在右边) ,而上面的是通过BinConverter转化后是高字节在右边低字节在左边.
 
 使用位操作
 在开发一些带权限控制的功能时我们有可能用到位操作,
 比方系统中有一些资源,每个资源对应一组操作,假设有8种操作
 这个时候你就可以设计这么一张表
资源用户操作表(用户名,资源号,操作类型)
一些数据:
             tools  1, 1
             tools  2, 2
             tools  1 , 3
             alsve  3, 1
             alsve  1,2

 
在上面我们用数字1~8表示8种操作,显然如果一个用户对某一资源拥有全部权限的话就需要8条记录来表示,如果用户达到几十万级别时这个表的数据量将会很庞大.

 改用位来表示操作

 资源用户操作表(用户名,资源号,操作数)
 这里我们使用了操作数,他是int类型的整数 我们使用其低8位来表示某用户对某资源拥有操作,对应位为1则表示有相应权限,为零则表示没有.

 在上面的规则下我们需要用到以下操作
 1.判断某一位是否为1 即用户是否拥有某资源的某一操作,
  bool表达式  (操作数 & (1<< 位置)) > 0;
 2.设置某一位为1,即将某一资源的某一操作分配给用户
 操作数=操作数 | (1<<位置);
 3. 设置某一位为0,即将用户对某一资源的某一操作取消
 操作数=操作数 &  (~(1<<位置)); //移位后,按位求反,再与操作数做与操作

一些实现细节 
用户登录后一次性将用户的资源操作数据加载到 Hashtable里(包括用户属于的角色分配的资源操作数据)
代码类似如下:
foreach(...){
 hash.Add("资源号","操作数") ;
}
 当然用户会属于一些角色的,而给角色分配的资源操作可能跟给用户分配的资源操作重叠,
 这个时候就需要将2者合并, 修改后的代码类似如下
foreach(....){
            if (hash.ContainsKey("资源号"))
            {
                hash["资源号"] = (int)hash["资源号"] | "操作数";
            }
            else
            {
                hash.Add("资源号", "操作数");
            }
}

  Hashtable可以方便的序列化,序列化后的数据可以保存在 Session(使用SQL保存Session)或者保存在加密的ViewState里面,当然同样可以把ViewState保存到SQL服务器里,不过,使用SQL Session 比较方便

 
 
 

原文地址:https://www.cnblogs.com/wdfrog/p/1245902.html