C#中枚举的位运算

c#

常见位运算

  • & :与,两个位都为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;

Related Posts

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注