如何在C#中循环遍历所有枚举值?

1726

这个问题已经有了一个答案:
如何在C#中枚举一个枚举? 26个答案

public enum Foos
{
    A,
    B,
    C
}

有没有一种方法可以循环遍历Foos的可能值?

基本上?

foreach(Foo in Foos)
8个回答

2468

是的,你可以使用GetValues方法:

var values = Enum.GetValues(typeof(Foos));

或者是打字版:

var values = Enum.GetValues(typeof(Foos)).Cast<Foos>();

我很久以前就在我的私人库中添加了一个辅助函数,专门用于这种情况:

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

使用方法:

var values = EnumUtil.GetValues<Foos>();

217
你可以直接使用以下代码来获取枚举类型的所有值,并将它们转换成数组:(T[])Enum.GetValues(typeof(T)) - Şafak Gür
51
@ŞafakGür的评论的好处是(1)不需要使用额外的迭代器(.Cast<Foos>),(2)也不需要对所有值进行装箱和拆箱。只要返回的数组类型不改变为其他类型(如object[]),Şafak的强制转换将保持有效。但我们可以完全确定他们不会这样做,因为(a)这会降低性能,(b)已经有数百万行代码使用Şafak的强制转换,如果出现运行时异常,它们都将无法正常工作。 - Jeppe Stig Nielsen
6
当然,有多少枚举会包含超过十几个值?我想在大多数情况下,装箱/拆箱的影响可以忽略不计,因此最干净的解决方案应该是最优先考虑的。 - Jon Coombs
15
@JCoombs,我认为这段代码已经很简洁了:public static IReadOnlyList<T> GetValues<T>() { return (T[])Enum.GetValues(typeof(T)); }。但是,在通常使用中,性能差异可以忽略不计。我只是不喜欢在已有可迭代对象的情况下创建一个迭代器的想法。 - Şafak Gür
13
很不幸,这并没有回答所提出的问题。问题是如何循环枚举的值。SLaks已经回答了这个问题。 - JAB
显示剩余10条评论

930
foreach(Foos foo in Enum.GetValues(typeof(Foos)))

24
这是一个很好的解决方案。通过使用“Foos”而不是“var”,类型推断系统能够使用正确版本的GetValues,返回正确的对象类型。不错! - Robert Patterson
8
使用 Foos 并不会自动推断出什么,这是显式转换。 - chtenb
7
@daveD 我认为人们应该可以独立处理编写foreach循环块的任务。 - Sinjai
2
@RobertPatterson 变量在这里工作,于2019年。 - silvalli

151

69
foreach (Foos foo in Enum.GetValues(typeof(Foos)))
{
    ...
}

重复回答亲爱的@arian - R.Akhlaghi
亲爱的 @arian,回答重复了。 - undefined

44

更新
有段时间后,我看到了一条评论,让我回想起我的旧答案,我觉得现在我会写得不同。如今我会写:

private static IEnumerable<T> GetEnumValues<T>()
{
    // Can't use type constraints on value types, so have to do check like this
    if (typeof(T).BaseType != typeof(Enum))
    {
        throw new ArgumentException("T must be of type System.Enum");
    }

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

2
为什么使用LINQ“更正确”?请参考您可以直接转换数组:(T[])Enum.GetValues(typeof(T)) @SafakGür,我认为这个版本的开销更小。 - Sebastian
10
获取枚举类型T的所有枚举值,其中T是一个枚举类型。简化:获取T枚举类型的所有枚举值。限定条件:T必须是枚举类型。 - Saboor Awan
2
@SaboorAwan无法将System.Enum用作类型参数约束。编译器会报错:'Constraint cannot be special class 'Enum''。 - Carlos Muñoz
是的,这就是为什么我在我的实现中加入了注释和类型检查的原因;我已经考虑过了。 :) - Neil Barnwell
7
快速提醒。在C# 7.3中,您现在可以将“枚举”(以及“非托管类型”和“委托”)用作通用约束。 - WBuck

39
static void Main(string[] args)
{
    foreach (int value in Enum.GetValues(typeof(DaysOfWeek)))
    {
        Console.WriteLine(((DaysOfWeek)value).ToString());
    }

    foreach (string value in Enum.GetNames(typeof(DaysOfWeek)))
    {
        Console.WriteLine(value);
    }
    Console.ReadLine();
}

public enum DaysOfWeek
{
    monday,
    tuesday,
    wednesday
}

13
 Enum.GetValues(typeof(Foos))

13

如果你正在使用.net5,它默认提供了一个通用版本。也就是说,不再需要像上面大多数示例中那样使用typeof()和强制转换。https://dev59.com/wnVD5IYBdhLWcg3wDXF3#65103244 - stoj

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