C#枚举进阶—用位运算实现方法一个参数传递多个枚举值
最近开发中遇到一些问题,我需要保存一系列的数据,我把保存的动作分开写成单独的方法,然后用一个总的方法来组合所有保存的动作。
伪代码如下:分别有三个已经封装好的方法,然后在SaveAll里面把这些方法组合起来。
void SaveAll()
{
// 保存表格数据
SaveTableData();
// 保存树形结构数据
SaveTreeViewData();
// 保存导入的信息
SaveImportData();
}
本来我有一个保存按钮,确实是要所有数据都保存,调用这个方法确实没问题。但有些按钮,只想保存导入的数据就行,有些按钮需要同时保存表格和树形结构的数据,不需要保存导入的数据。
有一个思路就是在需要保存不同数据的地方,分别都调用各自保存的方法,但这样我觉得管理起来很麻烦,我就只想调用SaveAll这一个方法,给它传指定的参数,去保存对应的数据。
于是我定义了一个枚举
public enum SaveOption
{
TableData,
TreeViewData,
ImportData,
}
SaveAll方法改造成
void SaveAll(SaveOption saveOpt)
{
if (saveOpt == saveOpt.TableData)
// 保存表格数据
SaveTableData();
if (saveOpt == saveOpt.TreeViewData)
// 保存树形结构数据
SaveTreeViewData();
if (saveOpt == saveOpt.ImportData)
// 保存导入的信息
SaveImportData();
}
这样,我就可以只调用SaveAll分行,传不同的参数,就可以分别保存不同的数据了。
但这样的弊端就是,每次只能传一个参数,如果我想保存表格数据、树形数据,就需要调用两次方法,传两次不同的参数。
我就想着有没有什么办法,可以一次传多个参数。
这就是今天要提到的枚举位运算传参。
枚举位运算
需要对枚举类进行改造:
- 一、 修改枚举类,变标记枚举
- 添加标记特性`[Flags]``
- 把枚举值都设置成2的x次方,用1左移x位就是2的x次方。
1 << 1: 即1左移1位就是2的1次方,即2
1 << 2: 即1左移2位就是2的2次方,即4
[Flags]
public enum SaveOption
{
TableData = 1
TreeViewData = 1 << 1,
ImportData = 1 << 2
}
- 二、传参时,使用按位或运算合并参数
比如我同时想保存表格数据,又想保存树形结构数据,调用方法时,传参的写法应如下:
SaveAll(SaveOption.TableData | SaveOption.TreeViewData);
- 三、 解析传参结果
上面传了两个参数,那如何知道传了哪些参数?用按位与(&)进行逆运算即可
改造SaveAll方法如下
void SaveAll(SaveOption saveOpt)
{
if ((saveOpt & SaveOption.TableData) == saveOpt.TableData)
// 保存表格数据
SaveTableData();
if ((saveOpt & SaveOption.TreeViewData) == saveOpt.TreeViewData)
// 保存树形结构数据
SaveTreeViewData();
if ((saveOpt & SaveOption.ImportData) == saveOpt.ImportData)
// 保存导入的信息
SaveImportData();
}
用传进来的参数按位与某个枚举,如果结果等于该枚举,说明传入的参数是中带有这个枚举值,从而执行对应的方法。
这就是实现了声明一个参数,但是可以传多个值,并且在方法内可以知道传入了哪些参数的效果了。
这样的写法,写起来比较简介。
比如我现在想保存表格数据和导入的数据。只需调用
SaveAll(SaveOption.TableData | SaveOption.ImportData);
这种写法就很灵活,复用性更强,管理也方便。
原理测试
上面是用C#的枚举来举例的,枚举的本质其实就是整数,只是有对应的名字而已,下面我用整数的代码来测试这个结果。
我有一些数字1、2、4、8、16。(注意,数值必须是2的n次方,不然按位与的结果会有重叠)
定义一个变量:i= 1 | 2;i的值是1按位或2。
然后用i分别按位与1、2、4、8、16,看结果
可以看到:i 按位与1、2的结果就是1、2本身,如果是按位与其它值,就是0。
用枚举位运算传参之后,判断传入的参数就是按这个原理。即用按位或传参,按位与逆运算回来。
具体的位运算结果,大家可以自行百度,有些是用按位或合并参数传参,有些是用按位左移传参,然后按位右移解析回来。