查看: 806|回复: 0

[ASP.NET教程] 枚举类型位标致[Flags]特性的使用以及为枚举类型添加方法

发表于 2017-10-22 07:36:24
太阳http代理AD

假设有段代码是这样的,需要判断角色装备哪些武器,然后根据角色的这个属性来进行其它的一些操作。这时候我们可以用枚举来标记角色可以装备的武器。

  1. public enum Equipment
  2. {
  3. 刀,
  4. 枪,
  5. 箭,
  6. }
  7. public sealed class Player
  8. {
  9. internal Equipment equipmentState;//用于描述角色可以使用哪些武器
  10. //......其它成员
  11. }
复制代码

这就有个问题了,当角色可以装备多种武器的时候,难道要用多个变量去表示他可以使用的武器吗?又或者是在Equipment类型中加入新的成员,刀和箭,刀和箭和弓...... 造成这种原因的是Player中的equipmentState只能表示一种状态,不能表示多种状态。

即它的值只能是刀,枪,箭,弓中的一个。

这时候可以用Flags特性为修饰Equipment类型。它可以让equipmentState有能力可以表示成多种状态,现在equipmentState就相当于集合一样。

  1. 1 namespace UsageOfFlagsAttribute
  2. 2 {
  3. 3 [Flags]
  4. 4 public enum Equipment
  5. 5 {
  6. 6 NONE = 0x0000,
  7. 7 刀 = 0x0001,
  8. 8 枪 = 0x0002,
  9. 9 箭 = 0x0004,
  10. 10 弓 = 0x0008
  11. 11 }
  12. 12
  13. 13 public sealed class Player
  14. 14 {
  15. 15 internal Equipment equipmentState;//用于描述角色可以使用哪些武器
  16. 16 }
  17. 17
  18. 18
  19. 19 class Program
  20. 20 {
  21. 21 static void Main(string[] args)
  22. 22 {
  23. 23 Player player = new Player();
  24. 24 player.equipmentState = Equipment.刀 | Equipment.弓; //可以表示成多种状态的集合
  25. 25 }
  26. 26 }
  27. 27 }
复制代码

用Flags标记后也就可以按位计算了,一般枚举有3种按位计算。

按位或(“|”):将指定的符号加入到枚举实例中

按位与(”&“):判断枚举实例中是否有指定的符号

异或(”^“):删除枚举实例中指定的符号

  1. class Program
  2. {
  3. static void Main(string[] args)
  4. {
  5. Player player = new Player();
  6. //按位或
  7. player.equipmentState = Equipment.刀;
  8. player.equipmentState = player.equipmentState | Equipment.弓;
  9. Console.WriteLine(player.equipmentState.ToString());//打印结果:刀,弓
  10. //按位与
  11. player.equipmentState = Equipment.刀 | Equipment.弓;
  12. player.equipmentState = player.equipmentState & Equipment.刀;
  13. Console.WriteLine(player.equipmentState.ToString()); //打印结果 : 刀
  14. //异或
  15. player.equipmentState = Equipment.刀 | Equipment.弓;
  16. player.equipmentState = player.equipmentState ^ Equipment.弓;
  17. Console.WriteLine(player.equipmentState.ToString()); //打印结果 : 刀
  18. Console.ReadKey();
  19. }
  20. }
复制代码

但是每次都要写 player.equipmentState = player.equipmentState ^ Equipment.弓; 这么赋值代码的可读性不好,而且容易浪费时间。因此可以扩展方法来封装这些操作。

  1. 1 public static class EnumExtendMethods
  2. 2 {
  3. 3 /// <summary>
  4. 4 /// 判断位标致的枚举实例中是否有指定符号
  5. 5 /// </summary>
  6. 6 /// <param name="eqipment">实例</param>
  7. 7 /// <param name="checkState">指定的符号</param>
  8. 8 /// <returns></returns>
  9. 9 public static bool Contains(this Equipment equipment,Equipment checkState)
  10. 10 {
  11. 11 if (checkState == 0)
  12. 12 {
  13. 13 throw new ArgumentOutOfRangeException("checkState", "不能为NONE");
  14. 14 }
  15. 15 return (equipment & checkState) == checkState;
  16. 16 }
  17. 17
  18. 18 /// <summary>
  19. 19 /// 将指定的符号从枚举实例中移除
  20. 20 /// </summary>
  21. 21 /// <param name="equipment"></param>
  22. 22 /// <param name="removeState">指定要移除的符号</param>
  23. 23 /// <returns></returns>
  24. 24 public static Equipment Remove(this Equipment equipment, Equipment removeState)
  25. 25 {
  26. 26 return equipment ^ removeState;
  27. 27 }
  28. 28
  29. 29 /// <summary>
  30. 30 /// 向枚举实例中加入指定的符号
  31. 31 /// </summary>
  32. 32 /// <param name="equipment"></param>
  33. 33 /// <param name="addState"></param>
  34. 34 /// <returns></returns>
  35. 35 public static Equipment Append(this Equipment equipment, Equipment addState)
  36. 36 {
  37. 37 return equipment | addState;
  38. 38 }
  39. 39 }
复制代码

现在可以这样调用了

  1. 1 class Program
  2. 2 {
  3. 3 static void Main(string[] args)
  4. 4 {
  5. 5 Player player = new Player();
  6. 6
  7. 7 //按位或
  8. 8 player.equipmentState = Equipment.刀;
  9. 9 player.equipmentState = player.equipmentState.Append(Equipment.弓);
  10. 10 Console.WriteLine(player.equipmentState.ToString());//打印结果:刀,弓
  11. 11
  12. 12 //按位与
  13. 13 player.equipmentState = Equipment.刀 | Equipment.弓;
  14. 14 if (player.equipmentState.Contains(Equipment.刀))
  15. 15 {
  16. 16 Console.WriteLine(player.equipmentState.ToString()); //打印结果 : 刀,弓
  17. 17 }
  18. 18
  19. 19 //异或
  20. 20 player.equipmentState = Equipment.刀 | Equipment.弓;
  21. 21 player.equipmentState = player.equipmentState.Remove(Equipment.弓);
  22. 22 Console.WriteLine(player.equipmentState.ToString()); //打印结果 : 刀
  23. 23
  24. 24 Console.ReadKey();
  25. 25 }
  26. 26 }
复制代码



太阳http代理AD
回复

使用道具 举报