常见位运算
- & :与,两个位都为1时,结果才为1
- | : 或,两个位任意一个为1时,结果为1
- ^ : 异或,两个位相同为0,相异为1
- ~ : 取反,0变1,1变0
- <<:左移运算符
>>
:右移运算符
枚举定义
假设我们想通过以下的枚举来给员工设置工作日:
public enum WeekDays
{
None,
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday,
Sunday,
}
普通的方法是定义一个数组,然后通过数组进行相关的计算。
var workDays = new WeekDays[]
{
WeekDays.Thursday,
WeekDays.Friday,
WeekDays.Saturday
}
如果通过位运算,则可以这样写:
var workDays = WeekDays.Thursday | WeekDays.Friday | WeekDays.Saturday;
但是并不是所有枚举值都支持这样操作,我们需要改造枚举的定义如下:
[Flags]
public enum WeekDays
{ //二进制 //十进制
None = 0, //0000000 0
Monday = 1 << 0, //0000001 1
Tuesday = 1 << 1, //0000010 2
Wednesday = 1 << 2, //0000100 4
Thursday = 1 << 3, //0001000 8
Friday = 1 << 4, //0010000 16
Saturday = 1 << 5, //0100000 32
Sunday = 1 << 6 //1000000 64
}
这里使用了左移运算符来定义枚举值,通过其对应的二进制值可以发现,每个枚举值对应的就是不同位上的1,而十进值则依次是2的n次方,很显然通过左移运算符来定义枚举更直观且不会出错。
对于 WeekDays.Thursday | WeekDays.Friday | WeekDays.Saturday ,转化成二进制来理解就是: 0001000 | 0010000 | 0100000 = 0111000, 正好第4,5,6位上的数是1,等同于星期四,星期五和星期六。
至于[Flags]这个属性,对运算结果没什么影响,但是如果ToString() 的话,则会不同。没有该属性时,ToString()的会输出对应的数值,加上该属性,则输出 Thursday,Friday,Saturday,因此更好理解。
示例
定义工作日
使用或运算
var workDays = WeekDays.Thursday | WeekDays.Friday | WeekDays.Saturday;
判断某一天是否属于工作日
可以使用与运算或者或运算
//可以这样
var isWorkDay = (WeekDays.Monday & workDays) !=0
//也可以这样
var isWorkDay = (WeekDays.Monday | workDays) == workDays
//还可以这样:
var isWorkDay = (WeekDays.Monday & workDays) == WeekDays.Monday
加上某一天
使用或运算
var newWorkDays = workDays | WeekDays.Wednesday;
去掉某一天
使用取反运算
var newWorkDays = workDays & ~ WeekDays.Friday;
切换工作日
使用异或运算,意思是如果原工作日包含周五,则去掉,否则加上。
var newWorkDays = workDays ^ WeekDays.Friday;