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

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

   public enum Equipment
    {
        刀,
        枪,
        箭,
        弓
    }

    public sealed class Player
    {
        internal Equipment equipmentState;//用于描述角色可以使用哪些武器
       //......其它成员
    }

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

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

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

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

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

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

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

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

  class Program
    {
        static void Main(string[] args)
        {
            Player player = new Player();

            //按位或
            player.equipmentState = Equipment.刀;
            player.equipmentState = player.equipmentState | Equipment.弓;
            Console.WriteLine(player.equipmentState.ToString());//打印结果:刀,弓

            //按位与
            player.equipmentState = Equipment.刀 | Equipment.弓;
            player.equipmentState = player.equipmentState & Equipment.刀;
            Console.WriteLine(player.equipmentState.ToString());  //打印结果 : 刀

            //异或
            player.equipmentState = Equipment.刀 | Equipment.弓;
            player.equipmentState = player.equipmentState ^ Equipment.弓;
            Console.WriteLine(player.equipmentState.ToString());  //打印结果 : 刀

            Console.ReadKey();
        }
    }

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

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

现在可以这样调用了

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

 

posted @ 2017-10-13 22:22  Marsir  阅读(1270)  评论(2编辑  收藏  举报