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     }
  • 相关阅读:
    MDX Step by Step 读书笔记(六) Building Complex Sets (复杂集合的处理) Filtering Sets
    在 Visual Studio 2012 开发 SSIS,SSAS,SSRS BI 项目
    微软BI 之SSIS 系列 在 SSIS 中读取 SharePoint List
    MDX Step by Step 读书笔记(五) Working with Expressions (MDX 表达式) Infinite Recursion 和 SOLVE_ORDER 原理解析
    MDX Step by Step 读书笔记(五) Working with Expressions (MDX 表达式)
    使用 SQL Server 2012 Analysis Services Tabular Mode 表格建模 图文教程
    MDX Step by Step 读书笔记(四) Working with Sets (使用集合) Limiting Set and AutoExists
    SQL Server 2012 Analysis Services Tabular Model 读书笔记
    Microsoft SQL Server 2008 MDX Step by Step 学习笔记连载目录
    2011新的开始,介绍一下AgileEAS.NET平台在新的一年中的发展方向
  • 原文地址:https://www.cnblogs.com/marsir/p/7663585.html
Copyright © 2011-2022 走看看