How to loop through all enum values in C#?
This question already has an answer here:
How do I enumerate an enum in C#? 26 answers
1 2 3 4 5 6
| public enum Foos
{
A,
B,
C
} |
是否有方法循环遍历Foos的可能值?
基本上?
是的,你能用吗?GetValue???s法:
1
| var values = Enum.GetValues(typeof(Foos )); |
或键入的版本:
1
| var values = Enum.GetValues(typeof(Foos )).Cast<Foos >(); |
我很久以前就为这样一个场合在我的私人图书馆中添加了一个助手函数:
1 2 3 4 5
| public static class EnumUtil {
public static IEnumerable <T > GetValues <T >() {
return Enum.GetValues(typeof(T )).Cast<T >();
}
} |
用途:
1
| var values = EnumUtil.GetValues<Foos>(); |
- 可以直接对数组进行强制转换:(T[])Enum.GetValues(typeof(T))。
- 关于@的好处?afagg&252;r的评论是:(1)您不必通过一个额外的迭代器(.Cast),以及(2)您不需要对所有的值进行装箱并再次取消装箱。?只要AFAK的强制转换不更改返回到其他类型(如object[]的数组类型),那么它的强制转换将保持有效。但是我们可以完全确定他们不会这样做,因为(a)它会失去性能,(b)已经有数以百万计的代码行在使用?AFAK的强制转换,它们都会因运行时异常而中断。
- 当然,有多少个枚举将包含十几个或两个以上的值?我认为在大多数情况下,装箱/拆箱是一个微不足道的打击,因此最干净的解决方案是最高优先级。
- @我觉得这个很干净:public static IReadOnlyList GetValues() { return (T[])Enum.GetValues(typeof(T)); }。但是,性能差异在普通用法中是可以忽略的。我只是不喜欢在我已经有一个可Iterable(Enumerable)对象要返回时创建迭代器的想法。
- 不幸的是,这并不能回答所提出的问题。问题是如何循环枚举的值。斯莱克斯回答了这个问题。
- @Jab,我认为它基本上回答了这个问题,只是有点含蓄。不是原来的"foos",我们应该有foreach (var v in values)。
- 此方法不允许我对返回的类型使用扩展方法。我有两个扩展方法,可以为每个枚举值提供一个友好的描述。使用此cast,我无法调用那些扩展方法。思想?
- 有人能为CompactFramework.net 3.5更新这个很好的答案吗?CompactFramework没有Enum.GetValues。谢谢
- 当我添加cast (Foos[])时,我的代码运行速度快了1.6倍。你自己试试。我用秒表测试了一个空前臂。for (int i = 0; i < 1000000; i++) foreach (Foos f in (Foos[])Enum.GetValues(typeof(Foos))) {}
- 通过强制转换到数组,您将依赖于可能发生更改的实现细节。如果微软将来在没有数组的情况下实现它,您的代码就会崩溃。如果性能是这样一个问题,那么您应该只缓存结果。
- @马索沃读了第三条评论。伟大的乔恩斯基特也使用它(链接)。微软不敢改变它。
- 我坚持我的意见。如果性能是这样一个问题,您应该缓存结果。我敢打赌,如果您真的多次调用这个函数,以至于它是一条热路径,那么在这种情况下,您要进行查找,并且通过将结果缓存到HashSet中,您将获得显著更好的性能。"微软不会改变它,因为我们都已经滥用它了"这是一个很糟糕的借口"。en.wikipedia.org/wiki/cratrial ou the ou commons
1
| foreach(Foos foo in Enum.GetValues(typeof(Foos ))) |
- 这是一个很好的解决方案。通过使用"foos"而不是"var",类型推断系统能够使用返回正确对象类型的正确版本的getValues。好极了!
- @罗伯特帕特森通过使用Foos没有什么可以神奇地推断出来。这是一个明确的演员阵容。
- @戴夫,我想人们可以自己写一个foreach块。
1 2 3 4
| foreach (EMyEnum val in Enum.GetValues(typeof(EMyEnum )))
{
Console .WriteLine(val );
} |
这里是jon skeet的功劳:http://bytes.com/groups/net-c/266447-how-loop-each-items-enum
1 2 3 4
| foreach (Foos foo in Enum.GetValues(typeof(Foos )))
{
...
} |
更新的一段时间后,我看到一条评论让我回到了我以前的答案,我想我现在会做不同的事情。这些天我会写:
1 2 3 4 5 6 7 8 9 10
| 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 >();
} |
- 为什么使用LINQ"更正确"?请到c.f.You can cast the array directly: (T[])Enum.GetValues(typeof(T))@safakg&252;r,这个版本的IMO开销更少。
- 简化getEnumValues,其中t:Enum
- @Saboorawan不能将System.Enum用作类型参数约束。编者说:Constraint cannot be special class 'Enum'。
- 是的,这就是为什么在我的实现中有那个注释和类型检查;我已经考虑过了。:)
- 快速注释。在C 7.3中,您现在可以使用Enum(以及unmanaged和delegate作为通用约束。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| 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
} |
对。在System.Enum类中使用GetValues()方法。