【问题标题】:How to group Enum values?如何对枚举值进行分组?
【发布时间】:2012-02-15 18:39:45
【问题描述】:

如何对枚举值进行分组?
假设我有一个像

这样的枚举
public enum Colors
  {
    LightBlue,
    LightGreen,
    DarkGreen,
    Black,
    White,
    LightGry,
    Yellow
  }

现在我想定义一些颜色组,例如浅色(LightBlue、LightGreen、White、LightGray、Yellow)和深色(Black、DarkGreen)。
所以我可以在我的代码中的不同位置请求组。
如果我没记错我的 Java 时间,我可以将方法添加到 Java 中的枚举中。我认为这在 C# 中是不可能的。但也许还有其他方法。

Edit1:当然我可以添加一个带有静态成员的实用程序类,例如IsADarkColor(Colors c)。但是我想在没有额外课程的情况下这样做,因为当我需要该功能时,我可能会忘记那个相关的课程。

【问题讨论】:

  • C# 不是 Java,编写类(在 Java 中甚至枚举也是一个对象)。

标签: c#


【解决方案1】:

我可以添加一个具有静态成员的实用程序类,例如IsADarkColor(Colors c)。但是我想在没有额外课程的情况下这样做,因为当我需要该功能时,我可能会忘记那个相关的课程。

这时扩展方法就派上用场了:

// Taking Reed Copsey's naming advice
public enum Color
{
    LightBlue,
    LightGreen,
    DarkGreen,
    Black,
    White,
    LightGray,
    Yellow
}

public static class Colors
{
    public static bool IsLightColor(this Color color)
    {
        switch(color){
            case Color.LightBlue:
            case Color.LightGreen:
            case Color.DarkGreen:
            case Color.LightGray:
            return true;
            default: 
            return false;
        }
    }
}

只要这两个类在同一个命名空间中,就可以看到静态方法好像属于 Color 类:

var color = Color.LightBlue;
if(color.IsLightColor()) {...}

(感谢@Abdul 让我想到了扩展方法)

【讨论】:

    【解决方案2】:

    你需要在课堂上写这个。

    就个人而言,我建议将其改写为 Color(单数)枚举和 Colors 类。然后Colors 类可以包含返回枚举“组”的方法或属性(即:IEnumerable<Color> LightColors { get { //...

    【讨论】:

    • 谢谢。如果没有更好的方法,我将使用该模式作为后备。
    【解决方案3】:

    您可以使用反射。
    首先你必须标记你的类别:

    public enum Colors
    {
        [Category("LightColor")]
        LightBlue,
        [Category("LightColor")]
        LightGreen,
        [Category("DarkColor")]
        DarkGreen,
        [Category("DarkColor")]
        Black,
        [Category("LightColor")]
        White,
        [Category("LightColor")]
        LightGry,
        [Category("LightColor")]
        Yellow
    }
    

    然后你应该创建一些帮助类/扩展方法来获取这些信息:

     public static string GetCategory(this Colors source)
        {
            FieldInfo fieldInfo = source.GetType().GetField(source.ToString());
    
            CategoryAttribute attribute = (CategoryAttribute)fieldInfo.GetCustomAttribute(typeof(CategoryAttribute), false);
    
            return attribute.Category;
        }
    

    你终于可以用 LINQ 做任何你想做的事了:

     var permissions = Enum.GetValues(typeof(Colors)).Cast<Colors>()
                .Select(x => new { Category = x.GetCategory(), Value = x.ToString() })
                .GroupBy(x => x.Category)
                .ToDictionary(grp => grp.Key, grp => grp.Select(x => x.Value).ToList());
    

    【讨论】:

      【解决方案4】:

      枚举没有子分组,但是在某些情况下,您可以使用按位运算在一定程度上实现此目的。 (请参阅this post 以获得体面的解释)

      老实说,我会坚持使用实用程序类,它没有什么乱七八糟的地方,这意味着您可以随着网站的发展添加其他描述、下拉操作等。

      【讨论】:

      • 谢谢。我不喜欢标记的枚举。我不知道为什么。
      【解决方案5】:

      我认为最简单的方法是指定一个范围内的值。例如:

      public enum Color
      {
          LightBlue,
          LightGreen,
          LightGray,
          White,
          Yellow,
          DarkGreen = 100,
          Black
      }
      

      那么所有大于 100 的值都应该是深色。您甚至可以为此添加扩展方法

      public bool static IsLightColor(this Color c)
      {
          return c < DarkGreen;
      }
      

      并像这样使用它:

       Color c = Color.LightBlue;
       if (c.IsLightColor())
       {
             // do something
       }
      

      【讨论】:

        【解决方案6】:

        可以使用标志和一些按位数学来管理像这样的简单分组。

            public class Program
            {
                public static void Main()
                {
                    var test = Colors.Red;
        
                    var isWarm = Constants.WarmColors.HasFlag(test);
                    var isCool = Constants.CoolColors.HasFlag(test);
        
                    Console.WriteLine(isWarm);  //true
                    Console.WriteLine(isCool);  //false
                }
        
                public static class Constants
                {
                    public static Colors CoolColors = Colors.Green | Colors.Blue | Colors.Purple;
                    public static Colors WarmColors = Colors.Red | Colors.Orange | Colors.Yellow;
                }
        
                [Flags]
                public enum Colors
                {
                    White = 0,
                    Red = 1,
                    Orange = 1 << 1,
                    Yellow = 1 << 2,
                    Green = 1 << 3,
                    Blue = 1 << 4,
                    Purple = 1 << 5,
                    Brown = 1 << 6,
                    Black = 1 << 7
                }
            }
        
        

        Bitwise and shift operators (C# reference)--微软)

        Logical and Bitwise Operators in C# -- Dániel Szabó/Plural Sight

        【讨论】:

        • 我有点惊讶[Flags] 方法尚未被提及,尽管在五年内发布了其他五个答案。在确定现有响应中的差距方面做得很好;这是一种更灵活的方法。顺便说一句,您可以通过枚举的枚举来管理这些分组,而不是引入常量类(例如,public enum ColorPalettes);除此之外,您的代码几乎与您现在的代码相同。
        【解决方案7】:

        在 C# 中你可以这样做(我不确定,你是否真的想要这个)

        public enum Colors
          {
            LightBlue,
            LightGreen,
            DarkGreen,
            Black,
            White,
            LightGry,
            Yellow
          }
        
        
        public enum LightColors{
           LightBlue = Colors.LightBlue, 
           LightGreen = Colors.LightGreen,
           White = Colors.White, 
           LightGray = Colors.LightGray, 
           Yellow = Colors.Yellow
        }
        public enum DarkColors{
           Black = Colors.Black, 
           DarkGreen = Colors.DarkGreen
        

        }

        【讨论】:

        • 这是一个有趣的技巧,但我不太喜欢创建应该代表相同基本事物的不同 类型 值的想法。例如,if(LightColors.LightBlue == Colors.LightBlue) 会产生编译时错误。
        • 非常有趣的方式。谢谢!
        • @StriplingWarrior 但您可以通过以下方式转换来做到这一点 if((int)LightColors.LightBlue == (int)Colors.LightBlue)
        • @StriplingWarrior 这是另一种方法。 if(Colors.Red.IsEqual(DarkColors.Red)) 并为枚举类创建一个扩展方法“IsEqual”,如下所示 public static class extension { public static bool IsEqual(this Enum color, DarkColors anotherColor) { return (byte)((颜色)颜色)==(字节)另一种颜色; } }
        猜你喜欢
        • 1970-01-01
        • 2016-06-23
        • 1970-01-01
        • 2014-10-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-05-07
        • 1970-01-01
        相关资源
        最近更新 更多