【问题标题】:Enum subset or subgroup in C#C# 中的枚举子集或子组
【发布时间】:2010-10-05 19:54:22
【问题描述】:

我有一个现有的枚举,其中包含许多项目。

我也有现有的代码可以用这个枚举做某些事情。

我现在想要一种仅查看子集枚举成员的方法。我正在寻找一种将我的枚举分成组的方法。我需要保留每个成员的 (int) 值,并且如果需要,我需要保留查看所有枚举成员的能力。

我唯一能想到的就是为每个子枚举创建一个新枚举,其中只包含我想要使用相同名称和值的项目。

这可行,但违反了整体不重复原则。

我不希望任何人有更好的选择,但我想我会问一下,以防万一有人给我看花哨的把戏。

谢谢,一如既往。

【问题讨论】:

  • 我认为没有办法做你想做的事(这取决于你所说的“视图”)。但如果你能描述更大的图景,或许有更好的方法来实现你的目标?
  • 我枚举的目的是让开发者可以根据它的名字选择一个特定的值。我的枚举变得太大,如果开发人员只能看到基于某个分组的枚举成员子集,有时会很好。该分组是固定的。

标签: c# enums


【解决方案1】:

您可以使用枚举定义值,然后通过静态类中的常量引用它们,这样您的开发人员就不会被大枚举所困扰。你可以:

enum MySuperEnumGroup
{
  Group1Item1,
  Group1Item2,
  Group1Item3,

  Group2Item1,
  Group2Item2,
  Group2Item3,

  Group3Item1,
  Group3Item2,
  Group3Item3,
}

static class MySuperEnumGroup_Group1
{
  public const MySuperEnumGroup Item1 = MySuperEnumGroup.Group1Item1;
  public const MySuperEnumGroup Item2 = MySuperEnumGroup.Group1Item2;
  public const MySuperEnumGroup Item3 = MySuperEnumGroup.Group1Item3;
}

static class MySuperEnumGroup_Group2
{
  public const MySuperEnumGroup Item1 = MySuperEnumGroup.Group2Item1;
  public const MySuperEnumGroup Item2 = MySuperEnumGroup.Group2Item2;
  public const MySuperEnumGroup Item3 = MySuperEnumGroup.Group2Item3;
}

//etc.

【讨论】:

  • 如何查看所有枚举成员?
【解决方案2】:

这可能会有所帮助:Fake Enums in C#

【讨论】:

  • 谢谢,这是一篇有趣的文章。
【解决方案3】:

最后,我不得不重写大部分代码,但衍生出以下“技巧”:

我丢弃了 C# 枚举并在常规类中使用静态成员。该类被制成单例,并在应用程序启动时初始化。

我的静态成员的构造函数被允许引用另一个静态成员作为“父”。

接下来,我的 init 方法使用反射来遍历每个静态成员,并根据几个属性对它们进行索引。这些索引存储在哈希表中,这些哈希表也是单例的成员。

我因此得到:

一个单例对象:

  • 具有可在设计时轻松访问的静态成员。
  • 可在运行时用于查找某些静态成员(基于“组”和其他属性)。

我的 init 方法进行了大量的验证。如果构建了无效(例如重复)的静态成员,则会在应用程序启动时出现运行时错误。

显然是一个相当大的 hack,但我对此很满意。

【讨论】:

    【解决方案4】:

    我会选择这个(至少在 VB.NET 中有效)

    enum MySuperEnumGroup 
    { 
      Group1Item1, 
      Group1Item2, 
      Group1Item3, 
    
      Group2Item1, 
      Group2Item2, 
      Group2Item3, 
    
      Group3Item1, 
      Group3Item2, 
      Group3Item3, 
    } 
    
    enum MySubEnumGroup 
    {
    Group2Item1 = MySuperEnumGroup.Group2Item1 
    Group3Item1 = MySuperEnumGroup.Group3Item1 
    Group3Item3 = MySuperEnumGroup.Group3Item3
    }
    

    然后在需要时执行某种 CType。

    【讨论】:

    • 我刚刚在 11 年前用我的名字在某个未注册的帐户上用一种很少编码的语言为某人提供了一个答案。老实说,我不知道是不是我。但它确实解决了我的问题。
    【解决方案5】:

    如果枚举没有明确的值,给它们一个并使用标志来定义“分组”:

    [Flags]
    enum MySuperEnumGroup
    {
        Group1 = 1 << 0,
        Group2 = 1 << 1,
        Group3 = 1 << 2,
    
        Group1Item1 = 1 << 10 | Group1,
        Group1Item2 = 1 << 11 | Group1,
        Group1Item3 = 1 << 12 | Group1,
    
        Group2Item1 = 1 << 13 | Group2,
        Group2Item2 = 1 << 14 | Group2,
        Group2Item3 = 1 << 15 | Group2,
    
        Group3Item1 = 1 << 16 | Group3,
        Group3Item2 = 1 << 17 | Group3,
        Group3Item3 = 1 << 18 | Group3,
    }
    

    然后您可以使用Enum.GetValuesHasFlag 来获取给定“分组”的值:

    var group1 = Enum.GetValues(typeof(MySuperEnumGroup))
                     .Cast<MySuperEnumGroup>()
                     .Where(value => value.HasFlag(MySuperEnumGroup.Group1))
                     .ToArray();
    

    【讨论】:

    • 我喜欢这种方法,我正在使用它的修改版本,其中组标识符从第 16 位及更高位开始,组中的项目从第 0、1、2 位开始,等以及您的 or'd 组标识符。您是否有理由让班组中的轮班职位独一无二?您是否发现我正在做的事情不是唯一的(没有 or-ing 组)?
    • @ChristopherKing 只要位数学有效,你就很好。请注意,超出&lt;&lt; 31 将溢出int,因此这最适用于小组枚举常量。如果你有很多,你可能想使用另一种方法,或者制作枚举: Int64,但这不是最佳选择。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-10-17
    • 2015-12-05
    • 1970-01-01
    • 2019-12-21
    • 1970-01-01
    • 2011-02-24
    • 2012-11-17
    相关资源
    最近更新 更多