【问题标题】:C# Iterating through an enum? (Indexing a System.Array)C# 遍历枚举? (索引 System.Array)
【发布时间】:2010-10-03 17:18:46
【问题描述】:

我有以下代码:

// Obtain the string names of all the elements within myEnum 
String[] names = Enum.GetNames( typeof( myEnum ) );

// Obtain the values of all the elements within myEnum 
Array values = Enum.GetValues( typeof( myEnum ) );

// Print the names and values to file
for ( int i = 0; i < names.Length; i++ )
{
    print( names[i], values[i] ); 
}

但是,我无法索引值。有没有更简单的方法来做到这一点?

或者我完全错过了什么!

【问题讨论】:

    标签: c# enums iteration system.array


    【解决方案1】:
    Array values = Enum.GetValues(typeof(myEnum));
    
    foreach( MyEnum val in values )
    {
       Console.WriteLine (String.Format("{0}: {1}", Enum.GetName(typeof(MyEnum), val), val));
    }
    

    或者,您可以转换返回的 System.Array:

    string[] names = Enum.GetNames(typeof(MyEnum));
    MyEnum[] values = (MyEnum[])Enum.GetValues(typeof(MyEnum));
    
    for( int i = 0; i < names.Length; i++ )
    {
        print(names[i], values[i]);
    }
    

    但是,您能确定 GetValues 返回值的顺序与 GetNames 返回名称的顺序相同吗?

    【讨论】:

    • "但是,您能确定 GetValues 返回值的顺序与 GetNames 返回名称的顺序相同吗?" - 这是一个很好的观点,我还没有解决!我认为您的第一个解决方案可能会提供一种可靠匹配值和字符串的方法
    • 您好,我之前已经看到有人提到这样做时会发生“索引不匹配”的怀疑;但是,我还没有发现这是否真的是一个问题?是否有任何确定的案例表明这种假设可能会出错?谢谢!
    • 如果您想解决Enum.GetName(typeof(MyEnum), val), (int)val) 中的值不匹配问题,您可能希望将第二个“val”转换为int,其中输出提供了枚举名称和编号。
    • GetValues 和 GetNames 返回的顺序相同,即:“返回值数组的元素按枚举常量的二进制值排序(即按其无符号大小)。”跨度>
    • 相信你也可以直接使用LINQ,在结果上调用Cast&lt;T&gt;Enum.GetValues(typeof(MyEnum)).Cast&lt;MyEnum&gt;()...
    【解决方案2】:

    你需要转换数组——返回的数组实际上是请求的类型,即myEnum[],如果你要求typeof(myEnum)

    myEnum[] values = (myEnum[]) Enum.GetValues(typeof(myEnum));
    

    然后values[0]

    【讨论】:

      【解决方案3】:

      您可以将该数组转换为不同类型的数组:

      myEnum[] values = (myEnum[])Enum.GetValues(typeof(myEnum));
      

      或者如果你想要整数值:

      int[] values = (int[])Enum.GetValues(typeof(myEnum));
      

      你当然可以迭代那些强制转换的数组:)

      【讨论】:

        【解决方案4】:

        字典列表怎么样?

        Dictionary<string, int> list = new Dictionary<string, int>();
        foreach( var item in Enum.GetNames(typeof(MyEnum)) )
        {
            list.Add(item, (int)Enum.Parse(typeof(MyEnum), item));
        }
        

        当然,您可以将字典值类型更改为您的枚举值。

        【讨论】:

        • 我认为这是要走的路,但不幸的是,枚举位于我无法控制的代码区域!
        • 我发现的唯一一种获取实际整数枚举值的解决方案!
        【解决方案5】:

        这是另一个。我们需要为我们的 EnumValues 提供友好的名称。我们使用 System.ComponentModel.DescriptionAttribute 为每个枚举值显示自定义字符串值。

        public static class StaticClass
        {
            public static string GetEnumDescription(Enum currentEnum)
            {
                string description = String.Empty;
                DescriptionAttribute da;
        
                FieldInfo fi = currentEnum.GetType().
                            GetField(currentEnum.ToString());
                da = (DescriptionAttribute)Attribute.GetCustomAttribute(fi,
                            typeof(DescriptionAttribute));
                if (da != null)
                    description = da.Description;
                else
                    description = currentEnum.ToString();
        
                return description;
            }
        
            public static List<string> GetEnumFormattedNames<TEnum>()
            {
                var enumType = typeof(TEnum);
                if (enumType == typeof(Enum))
                    throw new ArgumentException("typeof(TEnum) == System.Enum", "TEnum");
        
                if (!(enumType.IsEnum))
                    throw new ArgumentException(String.Format("typeof({0}).IsEnum == false", enumType), "TEnum");
        
                List<string> formattedNames = new List<string>();
                var list = Enum.GetValues(enumType).OfType<TEnum>().ToList<TEnum>();
        
                foreach (TEnum item in list)
                {
                    formattedNames.Add(GetEnumDescription(item as Enum));
                }
        
                return formattedNames;
            }
        }
        

        使用中

         public enum TestEnum
         { 
                [Description("Something 1")]
                Dr = 0,
                [Description("Something 2")]
                Mr = 1
         }
        
        
        
            static void Main(string[] args)
            {
        
                var vals = StaticClass.GetEnumFormattedNames<TestEnum>();
            }
        

        这将结束返回“Something 1”、“Something 2”

        【讨论】:

        • 只有在描述是静态的情况下才有用...如果您的描述需要基于实例进行更改,那么这种方法将不起作用。
        【解决方案6】:

        另一种解决方案,具有有趣的可能性:

        enum Days { Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday }
        
        static class Helpers
        {
        public static IEnumerable<Days> AllDays(Days First)
        {
          if (First == Days.Monday)
          {
             yield return Days.Monday;
             yield return Days.Tuesday;
             yield return Days.Wednesday;
             yield return Days.Thursday;
             yield return Days.Friday;
             yield return Days.Saturday;
             yield return Days.Sunday;
          } 
        
          if (First == Days.Saturday)
          {
             yield return Days.Saturday;
             yield return Days.Sunday;
             yield return Days.Monday;
             yield return Days.Tuesday;
             yield return Days.Wednesday;
             yield return Days.Thursday;
             yield return Days.Friday;
          } 
        }
        

        【讨论】:

          【解决方案7】:

          使用 foreach 循环怎么样,也许你可以使用它?

            int i = 0;
            foreach (var o in values)
            {
              print(names[i], o);
              i++;
            }
          

          大概是这样的吧?

          【讨论】:

          • 我有这个想法...但我需要在“同步”中访问名称和值...假设名称 [2] 与值 [2] 配对,我是不确定如何在 foreach 循环中实现这一点!
          • 我添加了一个示例 - 看看是否有帮助。
          【解决方案8】:

          老问题,但使用 LINQ 的 .Cast&lt;&gt;() 的方法稍微干净一些

          var values = Enum.GetValues(typeof(MyEnum)).Cast<MyEnum>();
          
          foreach(var val in values)
          {
              Console.WriteLine("Member: {0}",val.ToString());     
          }
          

          【讨论】:

            【解决方案9】:

            在 Enum.GetValues 结果中,转换为 int 会产生数值。使用 ToString() 生成友好名称。不需要对 Enum.GetName 进行其他调用。

            public enum MyEnum
            {
                FirstWord,
                SecondWord,
                Another = 5
            };
            
            // later in some method  
            
             StringBuilder sb = new StringBuilder();
             foreach (var val in Enum.GetValues(typeof(MyEnum))) {
               int numberValue = (int)val;
               string friendyName = val.ToString();
               sb.Append("Enum number " + numberValue + " has the name " + friendyName + "\n");
             }
             File.WriteAllText(@"C:\temp\myfile.txt", sb.ToString());
            
             // Produces the output file contents:
             /*
             Enum number 0 has the name FirstWord
             Enum number 1 has the name SecondWord
             Enum number 5 has the name Another
             */
            

            【讨论】:

              【解决方案10】:

              Array 有一个 GetValue(Int32) 方法,您可以使用它来检索指定索引处的值。

              Array.GetValue

              【讨论】:

                【解决方案11】:

                您可以使用格式字符串来简化此操作。我在使用消息中使用以下 sn-p:

                writer.WriteLine("Exit codes are a combination of the following:");
                foreach (ExitCodes value in Enum.GetValues(typeof(ExitCodes)))
                {
                    writer.WriteLine("   {0,4:D}: {0:G}", value);
                }
                

                D 格式说明符将枚举值格式化为十进制。还有一个提供十六进制输出的 X 说明符。

                G 说明符将枚举格式化为字符串。如果将 Flags 属性应用于枚举,则也支持组合值。有一个 F 说明符,就好像 Flags 总是存在一样。

                参见 Enum.Format()。

                【讨论】:

                  【解决方案12】:

                  这是一种遍历自定义 Enum 对象的简单方法

                  For Each enumValue As Integer In [Enum].GetValues(GetType(MyEnum))
                  
                       Print([Enum].GetName(GetType(MyEnum), enumValue).ToString)
                  
                  Next
                  

                  【讨论】:

                    【解决方案13】:

                    古老的问题,但 3Dave 的回答提供了最简单的方法。我需要一个小助手方法来生成一个 Sql 脚本来解码数据库中的枚举值以进行调试。效果很好:

                        public static string EnumToCheater<T>() {
                            var sql = "";
                            foreach (var enumValue in Enum.GetValues(typeof(T)))
                                sql += $@"when {(int) enumValue} then '{enumValue}' ";
                            return $@"case ?? {sql}else '??' end,";
                        }
                    

                    我有一个静态方法,所以用法是:

                    var cheater = MyStaticClass.EnumToCheater<MyEnum>()
                    

                    【讨论】:

                      猜你喜欢
                      • 1970-01-01
                      • 1970-01-01
                      • 1970-01-01
                      • 2010-12-12
                      • 2011-09-01
                      • 2015-08-13
                      • 1970-01-01
                      • 2016-06-08
                      • 2015-08-19
                      相关资源
                      最近更新 更多