应用范围:
当一个状态为多选时,使用此技术只要在数据库存一个byte类型的数据即可,大大减少代码与数据重复。
基础概念:
byte的概念:8位无符号整数。
byte的操作:
与,1与0=0,只有都是1的情况下才是1(C#中的操作符:&)
或,1或0=1,只要有1方是1,就是1(操作符:|)
原理:
十进制 | 二进制 |
1 | 00000001 |
2 | 00000010 |
4 | 00000100 |
8 | 00001000 |
16 | 00010000 |
32 | 00100000 |
64 | 01000000 |
128 | 10000000 |
建立的枚举值必须从上面表格中选择。
比如,选中的状态为,1,2,8,即:
00000001或00000010或00001000=00001011=11
那么我们需要存的就是11
那个如何通过11去分解出1,2,8呢
通过与操作:
00001011与00000001=00000001得1,同理得2,8
00001011与其它的数字=00000000。
故,只要判断00001011与00000001的结果是否等于00000001即可知道是否包含该状态!
实例:
首先我们建一个枚举:
enum Color : byte { red = 1, yellow = 2, blue = 4, green = 8 }
根据枚举邦定数据源:
var t = typeof(Color); var name = Enum.GetNames(t); Color[] value = Enum.GetValues(t) as Color[]; IDictionary<Color, string> datas = new Dictionary<Color, string>(name.Length); for (int i = 0; i < name.Length; i++) { datas.Add(value[i], name[i]); } CheckBoxList1.DataSource = datas.Select(i => new { k = (int)i.Key, v = i.Value }).ToList(); CheckBoxList1.DataTextField = "v"; CheckBoxList1.DataValueField = "k"; CheckBoxList1.DataBind();
我们假设已经从数据库中取到了一个值表示选中了blue,yellow,red;
表示为:
Color x = Color.blue | Color.yellow | Color.red;
根据x选中,关键是&的操作
foreach (ListItem item in CheckBoxList1.Items) { var m = (Color)byte.Parse(item.Value); if ((x & m) == m) { item.Selected = true; } }
取值就更简单了,取到的是int类型,在存入数据库时再进行转换:
int types = 0; foreach (ListItem item in CheckBoxList1.Items) { if (item.Selected == true) { types += int.Parse(item.Value); } }
注意,此状态的数量受到byte类型位数限制
实例下载:http://pan.baidu.com/s/1qWjm29Q