zoukankan      html  css  js  c++  java
  • 枚举类型位标致[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     }
  • 相关阅读:
    Java学习--泛型
    java学习--自定义类的实例的大小比较和排序
    Java学习--枚举
    java学习--修饰符
    Java学习--变量
    POI--各种样式的XSSFCellStyle的生成
    POI 使用颜色字符串生成XSSFColor对象
    Others # 看到的一些創意 / 知乎不錯的提問/ Android安全
    RO # 不错站点
    Linux # Virtual Box VBoxGuestAdditions.iso
  • 原文地址:https://www.cnblogs.com/marsir/p/7663585.html
Copyright © 2011-2022 走看看