如何在C#中枚举枚举?

例如,以下代码无法编译:

public enum Suit
{
    Spades,
    Hearts,
    Clubs,
    Diamonds
}

public void EnumerateAllSuitsDemoMethod()
{
    foreach (Suit suit in Suit)
    {
        DoSomething(suit);
    }
}

它给出了以下编译时错误:

“Suit”是“type”,但与“variable”类似

它在第二个Suit关键字上失败。


当前回答

我不认为这更好,甚至更好。我只是在陈述另一种解决方案。

如果枚举值的范围严格从0到n-1,则通用替代方法是:

public void EnumerateEnum<T>()
{
    int length = Enum.GetValues(typeof(T)).Length;
    for (var i = 0; i < length; i++)
    {
        var @enum = (T)(object)i;
    }
}

如果枚举值是连续的,并且可以提供枚举的第一个和最后一个元素,则:

public void EnumerateEnum()
{
    for (var i = Suit.Spade; i <= Suit.Diamond; i++)
    {
        var @enum = i;
    }
}

但这不是严格的枚举,只是循环。第二种方法比任何其他方法都快得多。。。

其他回答

将枚举转换为可以交互的对象的简单通用方法:

public static Dictionary<int, string> ToList<T>() where T : struct
{
   return ((IEnumerable<T>)Enum
       .GetValues(typeof(T)))
       .ToDictionary(
           item => Convert.ToInt32(item),
           item => item.ToString());
}

然后:

var enums = EnumHelper.ToList<MyEnum>();

我不认为这更好,甚至更好。我只是在陈述另一种解决方案。

如果枚举值的范围严格从0到n-1,则通用替代方法是:

public void EnumerateEnum<T>()
{
    int length = Enum.GetValues(typeof(T)).Length;
    for (var i = 0; i < length; i++)
    {
        var @enum = (T)(object)i;
    }
}

如果枚举值是连续的,并且可以提供枚举的第一个和最后一个元素,则:

public void EnumerateEnum()
{
    for (var i = Suit.Spade; i <= Suit.Diamond; i++)
    {
        var @enum = i;
    }
}

但这不是严格的枚举,只是循环。第二种方法比任何其他方法都快得多。。。

通过组合最重要的答案,我总结了一个非常简单的扩展:

public static class EnumExtensions
{
    /// <summary>
    /// Gets all items for an enum value.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="value">The value.</param>
    /// <returns></returns>
    public static IEnumerable<T> GetAllItems<T>(this T value) where T : Enum
    {
        return (T[])Enum.GetValues(typeof (T));
    }
}

它干净、简单,而且,根据@Jeppe Stig Nielsen的评论,速度很快。

将方法public static IEnumerable<T>GetValues<T>()添加到类中,如:

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

调用并传递枚举。现在您可以使用foreach遍历它:

 public static void EnumerateAllSuitsDemoMethod()
 {
     // Custom method
     var foos = GetValues<Suit>();
     foreach (var foo in foos)
     {
         // Do something
     }
 }

如果您需要在构建和运行时进行速度和类型检查,则此助手方法比使用LINQ来强制转换每个元素要好:

public static T[] GetEnumValues<T>() where T : struct, IComparable, IFormattable, IConvertible
{
    if (typeof(T).BaseType != typeof(Enum))
    {
        throw new ArgumentException(string.Format("{0} is not of type System.Enum", typeof(T)));
    }
    return Enum.GetValues(typeof(T)) as T[];
}

您可以按如下方式使用它:

static readonly YourEnum[] _values = GetEnumValues<YourEnum>();

当然,您可以返回IEnumerable<T>,但这不会给您带来任何好处。