【问题标题】:Is there a way to iterate through all enum values? [duplicate]有没有办法遍历所有枚举值? [复制]
【发布时间】:2010-09-14 07:58:33
【问题描述】:

可能重复:
C#: How to enumerate an enum?

主题说明了一切。我想用它在组合框中添加枚举的值。

谢谢

冰山

【问题讨论】:

    标签: c# enumeration


    【解决方案1】:

    您可以改为遍历 Enum.GetNames method 返回的数组。

    public class GetNamesTest {
        enum Colors { Red, Green, Blue, Yellow };
        enum Styles { Plaid, Striped, Tartan, Corduroy };
    
        public static void Main() {
    
            Console.WriteLine("The values of the Colors Enum are:");
            foreach(string s in Enum.GetNames(typeof(Colors)))
                Console.WriteLine(s);
    
            Console.WriteLine();
    
            Console.WriteLine("The values of the Styles Enum are:");
            foreach(string s in Enum.GetNames(typeof(Styles)))
                Console.WriteLine(s);
        }
    }
    

    【讨论】:

      【解决方案2】:

      使用枚举填充下拉列表的问题是枚举中不能有奇怪的字符或空格。我有一些扩展枚举的代码,以便您可以添加任何您想要的字符。

      像这样使用它..

      public enum eCarType
      {
          [StringValue("Saloon / Sedan")] Saloon = 5,
          [StringValue("Coupe")] Coupe = 4,
          [StringValue("Estate / Wagon")] Estate = 6,
          [StringValue("Hatchback")] Hatchback = 8,
          [StringValue("Utility")] Ute = 1,
      }
      

      像这样绑定数据..

      StringEnum CarTypes = new StringEnum(typeof(eCarTypes));
      cmbCarTypes.DataSource = CarTypes.GetGenericListValues();
      

      这是扩展枚举的类。

      // Author: Donny V.
      // blog: http://donnyvblog.blogspot.com
      
      using System;
      using System.Collections;
      using System.Collections.Generic;
      using System.Reflection;
      
      namespace xEnums
      {
      
          #region Class StringEnum
      
          /// <summary>
          /// Helper class for working with 'extended' enums using <see cref="StringValueAttribute"/> attributes.
          /// </summary>
          public class StringEnum
          {
              #region Instance implementation
      
              private Type _enumType;
              private static Hashtable _stringValues = new Hashtable();
      
              /// <summary>
              /// Creates a new <see cref="StringEnum"/> instance.
              /// </summary>
              /// <param name="enumType">Enum type.</param>
              public StringEnum(Type enumType)
              {
                  if (!enumType.IsEnum)
                      throw new ArgumentException(String.Format("Supplied type must be an Enum.  Type was {0}", enumType.ToString()));
      
                  _enumType = enumType;
              }
      
              /// <summary>
              /// Gets the string value associated with the given enum value.
              /// </summary>
              /// <param name="valueName">Name of the enum value.</param>
              /// <returns>String Value</returns>
              public string GetStringValue(string valueName)
              {
                  Enum enumType;
                  string stringValue = null;
                  try
                  {
                      enumType = (Enum) Enum.Parse(_enumType, valueName);
                      stringValue = GetStringValue(enumType);
                  }
                  catch (Exception) { }//Swallow!
      
                  return stringValue;
              }
      
              /// <summary>
              /// Gets the string values associated with the enum.
              /// </summary>
              /// <returns>String value array</returns>
              public Array GetStringValues()
              {
                  ArrayList values = new ArrayList();
                  //Look for our string value associated with fields in this enum
                  foreach (FieldInfo fi in _enumType.GetFields())
                  {
                      //Check for our custom attribute
                      StringValueAttribute[] attrs = fi.GetCustomAttributes(typeof (StringValueAttribute), false) as StringValueAttribute[];
                      if (attrs.Length > 0)
                          values.Add(attrs[0].Value);
      
                  }
      
                  return values.ToArray();
              }
      
              /// <summary>
              /// Gets the values as a 'bindable' list datasource.
              /// </summary>
              /// <returns>IList for data binding</returns>
              public IList GetListValues()
              {
                  Type underlyingType = Enum.GetUnderlyingType(_enumType);
                  ArrayList values = new ArrayList();
                  //List<string> values = new List<string>();
      
                  //Look for our string value associated with fields in this enum
                  foreach (FieldInfo fi in _enumType.GetFields())
                  {
                      //Check for our custom attribute
                      StringValueAttribute[] attrs = fi.GetCustomAttributes(typeof (StringValueAttribute), false) as StringValueAttribute[];
                      if (attrs.Length > 0)
                          values.Add(new DictionaryEntry(Convert.ChangeType(Enum.Parse(_enumType, fi.Name), underlyingType), attrs[0].Value));
      
                  }
      
                  return values;
      
              }
      
              /// <summary>
              /// Gets the values as a 'bindable' list<string> datasource.
              ///This is a newer version of 'GetListValues()'
              /// </summary>
              /// <returns>IList<string> for data binding</returns>
              public IList<string> GetGenericListValues()
              {
                  Type underlyingType = Enum.GetUnderlyingType(_enumType);
                  List<string> values = new List<string>();
      
                  //Look for our string value associated with fields in this enum
                  foreach (FieldInfo fi in _enumType.GetFields())
                  {
                      //Check for our custom attribute
                      StringValueAttribute[] attrs = fi.GetCustomAttributes(typeof(StringValueAttribute), false) as StringValueAttribute[];
                      if (attrs.Length > 0)
                          values.Add(attrs[0].Value);
                  }
      
                  return values;
      
              }
      
              /// <summary>
              /// Return the existence of the given string value within the enum.
              /// </summary>
              /// <param name="stringValue">String value.</param>
              /// <returns>Existence of the string value</returns>
              public bool IsStringDefined(string stringValue)
              {
                  return Parse(_enumType, stringValue) != null;
              }
      
              /// <summary>
              /// Return the existence of the given string value within the enum.
              /// </summary>
              /// <param name="stringValue">String value.</param>
              /// <param name="ignoreCase">Denotes whether to conduct a case-insensitive match on the supplied string value</param>
              /// <returns>Existence of the string value</returns>
              public bool IsStringDefined(string stringValue, bool ignoreCase)
              {
                  return Parse(_enumType, stringValue, ignoreCase) != null;
              }
      
              /// <summary>
              /// Gets the underlying enum type for this instance.
              /// </summary>
              /// <value></value>
              public Type EnumType
              {
                  get { return _enumType; }
              }
      
              #endregion
      
              #region Static implementation
      
              /// <summary>
              /// Gets a string value for a particular enum value.
              /// </summary>
              /// <param name="value">Value.</param>
              /// <returns>String Value associated via a <see cref="StringValueAttribute"/> attribute, or null if not found.</returns>
              public static string GetStringValue(Enum value)
              {
                  string output = null;
                  Type type = value.GetType();
      
                  if (_stringValues.ContainsKey(value))
                      output = (_stringValues[value] as StringValueAttribute).Value;
                  else 
                  {
                      //Look for our 'StringValueAttribute' in the field's custom attributes
                      FieldInfo fi = type.GetField(value.ToString());
                      StringValueAttribute[] attrs = fi.GetCustomAttributes(typeof (StringValueAttribute), false) as StringValueAttribute[];
                      if (attrs.Length > 0)
                      {
                          _stringValues.Add(value, attrs[0]);
                          output = attrs[0].Value;
                      }
      
                  }
                  return output;
      
              }
      
              /// <summary>
              /// Parses the supplied enum and string value to find an associated enum value (case sensitive).
              /// </summary>
              /// <param name="type">Type.</param>
              /// <param name="stringValue">String value.</param>
              /// <returns>Enum value associated with the string value, or null if not found.</returns>
              public static object Parse(Type type, string stringValue)
              {
                  return Parse(type, stringValue, false);
              }
      
              /// <summary>
              /// Parses the supplied enum and string value to find an associated enum value.
              /// </summary>
              /// <param name="type">Type.</param>
              /// <param name="stringValue">String value.</param>
              /// <param name="ignoreCase">Denotes whether to conduct a case-insensitive match on the supplied string value</param>
              /// <returns>Enum value associated with the string value, or null if not found.</returns>
              public static object Parse(Type type, string stringValue, bool ignoreCase)
              {
                  object output = null;
                  string enumStringValue = null;
      
                  if (!type.IsEnum)
                      throw new ArgumentException(String.Format("Supplied type must be an Enum.  Type was {0}", type.ToString()));
      
                  //Look for our string value associated with fields in this enum
                  foreach (FieldInfo fi in type.GetFields())
                  {
                      //Check for our custom attribute
                      StringValueAttribute[] attrs = fi.GetCustomAttributes(typeof (StringValueAttribute), false) as StringValueAttribute[];
                      if (attrs.Length > 0)
                          enumStringValue = attrs[0].Value;
      
                      //Check for equality then select actual enum value.
                      if (string.Compare(enumStringValue, stringValue, ignoreCase) == 0)
                      {
                          output = Enum.Parse(type, fi.Name);
                          break;
                      }
                  }
      
                  return output;
              }
      
              /// <summary>
              /// Return the existence of the given string value within the enum.
              /// </summary>
              /// <param name="stringValue">String value.</param>
              /// <param name="enumType">Type of enum</param>
              /// <returns>Existence of the string value</returns>
              public static bool IsStringDefined(Type enumType, string stringValue)
              {
                  return Parse(enumType, stringValue) != null;
              }
      
              /// <summary>
              /// Return the existence of the given string value within the enum.
              /// </summary>
              /// <param name="stringValue">String value.</param>
              /// <param name="enumType">Type of enum</param>
              /// <param name="ignoreCase">Denotes whether to conduct a case-insensitive match on the supplied string value</param>
              /// <returns>Existence of the string value</returns>
              public static bool IsStringDefined(Type enumType, string stringValue, bool ignoreCase)
              {
                  return Parse(enumType, stringValue, ignoreCase) != null;
              }
      
              #endregion
          }
      
          #endregion
      
          #region Class StringValueAttribute
      
          /// <summary>
          /// Simple attribute class for storing String Values
          /// </summary>
          public class StringValueAttribute : Attribute
          {
              private string _value;
      
              /// <summary>
              /// Creates a new <see cref="StringValueAttribute"/> instance.
              /// </summary>
              /// <param name="value">Value.</param>
              public StringValueAttribute(string value)
              {
                  _value = value;
              }
      
              /// <summary>
              /// Gets the value.
              /// </summary>
              /// <value></value>
              public string Value
              {
                  get { return _value; }
              }
          }
      
          #endregion
      }
      

      【讨论】:

        【解决方案3】:

        .NET 3.5 通过使用扩展方法使其变得简单:

        enum Color {Red, Green, Blue}
        

        可以迭代

        Enum.GetValues(typeof(Color)).Cast<Color>()
        

        或者定义一个新的静态泛型方法:

        static IEnumerable<T> GetValues<T>() {
          return Enum.GetValues(typeof(T)).Cast<T>();
        }
        

        请记住,使用 Enum.GetValues() 方法进行迭代会使用反射,因此会降低性能。

        【讨论】:

          【解决方案4】:

          我知道其他人已经回答了正确的答案,但是,如果您想在组合框中使用枚举,您可能需要额外的码数并将字符串与枚举相关联,以便您可以提供更多显示字符串中的详细信息(例如单词之间的空格或使用与您的编码标准不匹配的大小写的显示字符串)

          这篇博文可能有用 - Associating Strings with enums in c#

          public enum States
          {
              California,
              [Description("New Mexico")]
              NewMexico,
              [Description("New York")]
              NewYork,
              [Description("South Carolina")]
              SouthCarolina,
              Tennessee,
              Washington
          }
          

          作为奖励,他还提供了一个实用方法来枚举我现在用 Jon Skeet 的 cmets 更新的枚举

          public static IEnumerable<T> EnumToList<T>()
              where T : struct
          {
              Type enumType = typeof(T);
          
              // Can't use generic type constraints on value types,
              // so have to do check like this
              if (enumType.BaseType != typeof(Enum))
                  throw new ArgumentException("T must be of type System.Enum");
          
              Array enumValArray = Enum.GetValues(enumType);
              List<T> enumValList = new List<T>();
          
              foreach (T val in enumValArray)
              {
                  enumValList.Add(val.ToString());
              }
          
              return enumValList;
          }
          

          Jon 还指出,在 C# 3.0 中,它可以简化为这样的东西(现在它变得如此轻量级,我想你可以直接在线完成):

          public static IEnumerable<T> EnumToList<T>()
              where T : struct
          {
              return Enum.GetValues(typeof(T)).Cast<T>();
          }
          
          // Using above method
          statesComboBox.Items = EnumToList<States>();
          
          // Inline
          statesComboBox.Items = Enum.GetValues(typeof(States)).Cast<States>();
          

          【讨论】:

          • @Ray - 我打算发布同一篇博文的链接 :-) 我已经多次使用他的实用程序,它就像一个魅力!
          • 一些改进(恐怕可能需要一些 cmets): 1) 该方法可以添加“where T : struct”约束以降低 ArgumentException 的可能性(尽管仍然可能)。 2)foreach可以使用“foreach(T val in enumValArray)”代替格式化再重新解析。
          • 如果您使用的是 .NET 3.5,只需执行以下操作即可: return Enum.GetValues(typeof(T)).Cast();这也不会打扰建立一个列表:)
          • 谢谢 Jom.. 顺便说一句,你拿到书了——一旦我的团队把书还给我,我会读的! ;-) 他们似乎喜欢它...
          • 糟糕,乔恩不是乔姆(我必须等待 30 秒才能更正!)
          【解决方案5】:

          有点“复杂”(可能有点矫枉过正),但我使用这两种方法返回字典以用作数据源。第一个返回名称作为键,第二个值作为键返回。

          公共静态 IDictionary ConvertEnumToDictionaryNameFirst() { if (typeof(K).BaseType != typeof(Enum)) { 抛出新的 InvalidCastException(); } return Enum.GetValues(typeof(K)).Cast().ToDictionary(currentItem => Enum.GetName(typeof(K), currentItem)); }

          或者你可以这样做

          公共静态 IDictionary ConvertEnumToDictionaryValueFirst() { if (typeof(K).BaseType != typeof(Enum)) { 抛出新的 InvalidCastException(); } return Enum.GetNames(typeof(K)).Cast().ToDictionary(currentItem => (int)Enum.Parse(typeof(K), currentItem)); }

          这假设您使用的是 3.5。如果没有,您必须替换 lambda 表达式。

          用途:

          字典列表 = ConvertEnumToDictionaryValueFirst(); 使用系统; 使用 System.Collections.Generic; 使用 System.Linq;

          【讨论】:

            【解决方案6】:

            如果您需要组合的值与枚举的值相对应,您也可以使用以下内容:

            foreach (TheEnum value in Enum.GetValues(typeof(TheEnum)))
                dropDown.Items.Add(new ListItem(
                    value.ToString(), ((int)value).ToString()
                );
            

            通过这种方式,您可以在下拉列表中显示文本并取回值(在 SelectedValue 属性中)

            【讨论】:

              【解决方案7】:

              使用 Enum.GetValues 方法:

              foreach (TestEnum en in Enum.GetValues(typeof(TestEnum)))
              {
                  ...
              }
              

              您不需要将它们转换为字符串,这样您就可以通过将 SelectedItem 属性直接转换为 TestEnum 值来检索它们。

              【讨论】:

                【解决方案8】:

                在枚举中定义最小值和最大值通常很有用,它们始终是第一项和最后一项。下面是一个使用 Delphi 语法的非常简单的示例:

                procedure TForm1.Button1Click(Sender: TObject);
                type
                  TEmployeeTypes = (etMin, etHourly, etSalary, etContractor, etMax);
                var
                  i : TEmployeeTypes;
                begin
                  for i := etMin to etMax do begin
                    //do something
                  end;
                end;
                

                【讨论】:

                • 除了没有匹配的 C# 语法,所以其他示例可能更好!就我个人而言,我认为 min/max 不适合枚举,如果我要定义交通信号灯,我想要 Red、Amber、Green 而不是 Min、Red、Amber、Green、Min。
                • 呃... ...格林,马克斯。 (哎呀)
                【解决方案9】:
                string[] names = Enum.GetNames (typeof(MyEnum));
                

                然后用数组填充下拉列表

                【讨论】:

                  猜你喜欢
                  • 2014-02-17
                  • 1970-01-01
                  • 2010-11-01
                  • 2015-03-17
                  • 1970-01-01
                  • 2013-05-31
                  相关资源
                  最近更新 更多