如何在C#中枚举枚举?

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

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

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

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

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

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


当前回答

新的.NET 5解决方案:

.NET 5为GetValues方法引入了新的通用版本:

Suit[] suitValues = Enum.GetValues<Suit>();

这是目前为止最方便的方法。

foreach循环中的用法:

foreach (Suit suit in Enum.GetValues<Suit>())
{

}

如果您只需要枚举名作为字符串,则可以使用通用的GetNames方法:

string[] suitNames = Enum.GetNames<Suit>();

其他回答

当你有这样的枚举时

enum DemoFlags
{
    DemoFlag = 1,
    OtherFlag = 2,
    TestFlag = 4,
    LastFlag = 8,
}

有了这个任务

DemoFlags demoFlags = DemoFlags.DemoFlag | DemoFlags.TestFlag;

需要这样的结果

"DemoFlag | TestFlag"

此方法有助于:

public static string ConvertToEnumString<T>(T enumToConvert, string separator = " | ") where T : Enum
{
    StringBuilder convertedEnums = new StringBuilder();

    foreach (T enumValue in Enum.GetValues(typeof(T)))
    {
        if (enumToConvert.HasFlag(enumValue)) convertedEnums.Append($"{ enumValue }{separator}");
    }

    if (convertedEnums.Length > 0) convertedEnums.Length -= separator.Length;

    return convertedEnums.ToString();
}

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

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的评论,速度很快。

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

如果枚举值的范围严格从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;
    }
}

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

三种方式:

Enum.GetValues(类型)//自.NET 1.1起,不在Silverlight或.NET Compact Framework中type.GetEnumValues()//仅适用于.NET 4及更高版本type.GetFields()。其中(x=>x.IsLiteral)。Select(x=>x.GetValue(null))//在任何地方都有效

我不确定为什么在类型实例上引入GetEnumValues。对我来说,它一点也不可读。


拥有Enum<T>这样的助手类对我来说是最可读和难忘的:

public static class Enum<T> where T : struct, IComparable, IFormattable, IConvertible
{
    public static IEnumerable<T> GetValues()
    {
        return (T[])Enum.GetValues(typeof(T));
    }

    public static IEnumerable<string> GetNames()
    {
        return Enum.GetNames(typeof(T));
    }
}

现在您拨打:

Enum<Suit>.GetValues();

// Or
Enum.GetValues(typeof(Suit)); // Pretty consistent style

如果性能很重要,也可以使用某种缓存,但我不认为这是一个问题。

public static class Enum<T> where T : struct, IComparable, IFormattable, IConvertible
{
    // Lazily loaded
    static T[] values;
    static string[] names;

    public static IEnumerable<T> GetValues()
    {
        return values ?? (values = (T[])Enum.GetValues(typeof(T)));
    }

    public static IEnumerable<string> GetNames()
    {
        return names ?? (names = Enum.GetNames(typeof(T)));
    }
}

将方法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
     }
 }