【问题标题】:looping through enum values遍历枚举值
【发布时间】:2010-12-12 08:57:55
【问题描述】:

是否可以在 Objective-C 中遍历枚举值?

【问题讨论】:

  • 重新标记:这是(AFAIK)一个纯 C 问题。使用更通用的标记,您将获得更多响应。
  • 它还回答了人们在 Obj-C 中搜索它的问题。添加了那个标签。

标签: c objective-c enums


【解决方案1】:

如果上述方法不适合您,因为您使用的是 C++,the following should:

enum Foo {
  One,
  Two,
  Three,
  Last
};

for ( int fooInt = One; fooInt != Last; fooInt++ )
{
   Foo foo = static_cast<Foo>(fooInt);
   // ...
}

【讨论】:

    【解决方案2】:

    我讨厌用“最后一个”条目弄脏我的枚举(以及附带的注意事项,即不应该使用它,并且必须始终保留它,嗯,最后),并且只找到了一种解决方法(除了使用最后一个枚举条目作为秘密“最后一个”,这再次让我感到恶心)。

    如果您使用X Macros 定义您的枚举,您可以非常简单地计算您的枚举中的项目数。请参阅链接 FMI,了解何时可以使用此方法 - 为简明扼要,如下所示:

    #define COLOR_TABLE \
    X(red, "red")       \
    X(green, "green")   \
    X(blue, "blue")
    
    #define X(a, b) a,
    enum COLOR {
      COLOR_TABLE
    };
    #undef X
    
    #define X(a, b) b,
    char *color_name[] = {
      COLOR_TABLE
    };
    #undef X
    
    #define X(a, b) +1
    int color_count = 0 COLOR_TABLE;
    #undef X
    

    【讨论】:

      【解决方案3】:

      给定

      enum Foo {Bar=0,Baz,...,Last};
      

      你可以像这样迭代元素:

      for(int i=Bar; i<=Last; i++) {
        ...
      }
      

      请注意,这暴露了 C 枚举的真正只是一个整数的性质。特别是,您可以看到 C 枚举并没有真正提供类型安全,因为您可以使用 int 代替枚举值,反之亦然。此外,这取决于枚举值的声明顺序:至少可以说是脆弱的。另外,请看Chuck的评论;如果枚举项是不连续的(例如,因为您为某些项指定了显式的、非顺序的值),这根本不起作用。哎呀。

      【讨论】:

      • 它还要求枚举中的所有项目都是连续的。但这是你能得到的最好的。
      • 我无法识别 for looo 中的 Foo。
      • 纯属吹毛求疵,但拼写为vice versa
      • @MilesRout 实际上至少有 6 个字符的字符变化。由于它是 2 个字符的修复,我无法修复它。
      • 注意,如果值不是连续的,而是位掩码枚举,可以使用:for (int i=1; i&lt;=Last; i=i*2)
      【解决方案4】:

      可以通过获取枚举中的名称数组并利用数组的长度来确定任何枚举的长度(项目数)。使用 Enum 的 GetNames 方法。 Enum.GetNames(enumType).Length.

      {
      enum Pig { Snort, Sty, Oink, Curly };
      const int Pig_Count = Enum.GetNames(typeof(Pig)).Length;
      }
      

      【讨论】:

        【解决方案5】:

        对于非连续枚举,您可以通过以下方式迭代有效值:

        enum {
            value_one   = 0,
            value_two   = 1,
            value_three = 3,
            value_max
        }
        for ( i = value_one; i < value_max; i++ )
        { 
            switch(i)
            {
                case value_one:
                case value_two:
                case value_three:
                case value_four:
                {
                    /* ... Do something with valid enum value ... */
                }
                break;
                default:
                    /* Found an invalid enum entry; ignore it */
                break;
            }
        }
        

        【讨论】:

        • 在这种情况下,我根本不会使用循环。一个接一个地留下开关盒,这样会更干净,有时效率更高。
        • 当然,我完全同意你的观点,我不会在生产代码中写这个;我将开关封装在循环中的唯一原因是因为这是原始海报所要求的;)
        【解决方案6】:

        为了寻找这个,我只是炮制了以下满足我自己要求的解决方案。我想我会把它贴在这里,供搜索类似内容的人使用。

        假设我有一个枚举。

        typedef NS_ENUM (NSInteger, ISDirection) {
          ISDirectionUp,
          ISDirectionDown,
          ISDirectionLeft,
          ISDirectionRight
        };
        

        为了能够循环它,我定义了以下预处理器宏。

        #define ISDirectionAllAsDir ISDirection dir = ISDirectionUp; dir <= ISDirectionRight; dir++
        

        然后我在循环中使用它,如下所示:

        for(ISDirectionAllAsDir) {
          NSLog(@"Direction %d", dir);
        }
        

        这将迭代的逻辑放在一个地方(宏),从而提高了代码的可维护性。

        【讨论】:

          【解决方案7】:

          我喜欢我从这里得到的东西 Iteration over enum in Objective C?

          typedef enum { ENUM1=0,  ENUM2, ENUM3, ENUM4 , TOTAL  } ;
          
          
          for ( int i=ENUM1 ; i<TOTAL; i++)
          {}
          

          这样你以后可以继续添加枚举而不影响你的循环吗?

          【讨论】:

            【解决方案8】:

            这有点杂乱无章(整个概念也是如此......嗯......)但如果您要多次执行此操作,并且您希望能够处理非连续枚举,您可以创建一个(全局常量)数组,并具有(使用 ennukiller 的示例)方向方向[4] = {东、西、北、南}; 然后在你的循环中你可以谈论方向[i]而不是直接迭代方向本身......

            正如我所说,它很丑,但我认为它不那么脆弱......

            【讨论】:

            • 我觉得不错。有没有一种方法可以添加某种宏,为我们声明的每个枚举类型自动生成 C 数组?
            • @ArtOfWarfare 我一直在使用它:#define ENUM(type, ...) enum _##type { __VA_ARGS__ }; enum _##type type##s[] = { __VA_ARGS__ },尽管这只适用于连续的。我不使用不连续的枚举,因为这对我来说意味着糟糕的设计。此外,我的 C 代码中到处都有使用此宏的 typedef struct _list List;typedef enum _direction Direction,这就是为什么我在类型前面加上 _ 的原因。 ENUM(direction, NORTH, EAST, SOUTH, WEST); 给了enum _direction { NORTH, EAST, SOUTH, WEST }; enum _direction directions = { NORTH, EAST, SOUTH, WEST }; 我喜欢。
            【解决方案9】:

            如果你的枚举定义如下:

            enum Direction {  East,  West,  North,  South};
            

            你可以这样循环:

            for ( int direction = East; direction <= South; ++direction)
            {
               /* Do something with Direction
            }
            

            【讨论】:

            • 我从来没有这样做过,所以我有一些问题。不应该是Direction.East 和Direction.South 吗?条件也不应该是方向
            • 有更好的方法吗?只是好奇,但似乎取决于枚举值的声明顺序充其量是脆弱的。
            • @blaenk:我认为您将结构与枚举混淆了。
            • @Ed:是的,这很脆弱,没有更好的方法。根本不建议这样做。
            • 一个可以更明确,如 enum Direction { East =1, West=2, North=3, South=4};甚至枚举 Direction { East =313, West, North, South};但这一切都归结为同一件事,除了对每个元素进行编号为程序员错误留出了更多空间。最后,在我看来,它与任何 const 声明一样脆弱或非脆弱。
            猜你喜欢
            • 1970-01-01
            • 2011-09-01
            • 1970-01-01
            • 2015-08-13
            • 1970-01-01
            • 2014-07-26
            • 1970-01-01
            • 2016-06-08
            • 2015-08-19
            相关资源
            最近更新 更多