有没有一种方法可以遍历所有枚举值?

33

可能重复:
C#:如何枚举枚举类型?

问题已经说得很清楚了,我想使用它来将枚举类型的值添加到组合框中。

谢谢

vIceBerg

9个回答

31
string[] names = Enum.GetNames (typeof(MyEnum));

然后只需使用数组填充下拉列表即可。


25
我知道其他人已经给出了正确的答案,但是如果你想在组合框中使用枚举,你可能需要额外努力将字符串与枚举关联起来,这样你就可以在显示的字符串中提供更多细节(例如单词之间的空格或使用与您的编码标准不匹配的大小写格式的显示字符串)。
这篇博客文章可能会有用- 在c#中将字符串与枚举关联
public enum States
{
    California,
    [Description("New Mexico")]
    NewMexico,
    [Description("New York")]
    NewYork,
    [Description("South Carolina")]
    SouthCarolina,
    Tennessee,
    Washington
}

作为额外的好处,他还提供了一个实用方法来枚举我现在已经根据Jon Skeet的评论进行了更新的枚举。
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 - 我本来要贴同样的博客链接 :-) 我已经多次使用他的实用程序,它非常好用! - Metro Smurf
1
一些改进(可能需要一些注释):1)该方法可以添加“where T:struct”约束,以使ArgumentException的发生几率降低(尽管仍然有可能)。2)foreach可以使用“foreach(T val in enumValArray)”而不是格式化然后重新解析。 - Jon Skeet
如果你正在使用.NET 3.5,只需要这样做:return Enum.GetValues(typeof(T)).Cast<T>();这样就不需要构建列表 :) - Jon Skeet
谢谢Jom。顺便说一句,我拿到了你的书——等我的团队把它还给我后,我会读的!;-) 他们似乎很喜欢它... - Ray Hayes
哎呀,是Jon不是Jom(我还得等30秒才能更正!) - Ray Hayes

10

使用 Enum.GetValues 方法:

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

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


5
你可以遍历由Enum.GetNames方法返回的数组。
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);
    }
}

5
如果您需要组合框的值与枚举值对应,您也可以使用以下方式:
```html

如果您需要组合框的值与枚举值对应,您还可以使用以下方式:

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

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

1
使用枚举来填充下拉菜单的问题在于枚举中不能包含奇怪的字符或空格。我有一些代码可以扩展枚举,让你可以添加任何字符。
像这样使用它...
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
}

1

.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()方法进行迭代会使用反射,因此会有性能损失。

0

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

public static IDictionary<string, int> ConvertEnumToDictionaryNameFirst<K>()
{
  if (typeof(K).BaseType != typeof(Enum))
  {
    throw new InvalidCastException();
  }
return Enum.GetValues(typeof(K)).Cast<int>().ToDictionary(currentItem => Enum.GetName(typeof(K), currentItem)); }

或者你可以这样做

public static IDictionary<int, string> ConvertEnumToDictionaryValueFirst<K>()
{
  if (typeof(K).BaseType != typeof(Enum))
  {
    throw new InvalidCastException();
  }
return Enum.GetNames(typeof(K)).Cast<string>().ToDictionary(currentItem => (int)Enum.Parse(typeof(K), currentItem)); }

这假设您正在使用3.5版本。如果不是,则必须替换lambda表达式。

用法:

  Dictionary list = ConvertEnumToDictionaryValueFirst<SomeEnum>();

  using System;
  using System.Collections.Generic;
  using System.Linq;

0
通常有用的是在枚举内定义一个Min和Max,它们将始终是第一和最后一项。以下是使用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不适合枚举,如果我要定义一个交通信号灯,我想要红色、黄色、绿色,而不是Min、红色、黄色、绿色、Min。 - Ray Hayes
额... ...格林,马克斯。(哎呀) - Ray Hayes

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接