C# 如何枚举一个枚举
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/105372/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to enumerate an enum
提问by Ian Boyd
How can you enumerate an enum
in C#?
如何enum
在 C# 中枚举一个?
E.g. the following code does not compile:
例如,以下代码无法编译:
public enum Suit
{
Spades,
Hearts,
Clubs,
Diamonds
}
public void EnumerateAllSuitsDemoMethod()
{
foreach (Suit suit in Suit)
{
DoSomething(suit);
}
}
And it gives the following compile-time error:
它给出了以下编译时错误:
'Suit' is a 'type' but is used like a 'variable'
“西装”是一种“类型”,但像“变量”一样使用
It fails on the Suit
keyword, the second one.
它在Suit
关键字上失败,第二个。
采纳答案by jop
foreach (Suit suit in (Suit[]) Enum.GetValues(typeof(Suit)))
{
}
Note: The cast to (Suit[])
is not strictly necessary, but it does make the code 0.5 ns faster.
注意:强制转换(Suit[])
不是必需的,但它确实使代码快了 0.5 ns。
回答by Tom Carr
I think you can use
我想你可以用
Enum.GetNames(Suit)
回答by Haacked
It looks to me like you really want to print out the names of each enum, rather than the values. In which case Enum.GetNames()
seems to be the right approach.
在我看来,您真的想打印出每个枚举的名称,而不是值。在这种情况下Enum.GetNames()
似乎是正确的方法。
public enum Suits
{
Spades,
Hearts,
Clubs,
Diamonds,
NumSuits
}
public void PrintAllSuits()
{
foreach (string name in Enum.GetNames(typeof(Suits)))
{
System.Console.WriteLine(name);
}
}
By the way, incrementing the value is not a good way to enumerate the values of an enum. You should do this instead.
顺便说一句,增加值并不是枚举枚举值的好方法。你应该这样做。
I would use Enum.GetValues(typeof(Suit))
instead.
我会用Enum.GetValues(typeof(Suit))
。
public enum Suits
{
Spades,
Hearts,
Clubs,
Diamonds,
NumSuits
}
public void PrintAllSuits()
{
foreach (var suit in Enum.GetValues(typeof(Suits)))
{
System.Console.WriteLine(suit.ToString());
}
}
回答by Joshua Drake
public void PrintAllSuits()
{
foreach(string suit in Enum.GetNames(typeof(Suits)))
{
Console.WriteLine(suit);
}
}
回答by bob
I made some extensions for easy enum usage. Maybe someone can use it...
我做了一些扩展以方便枚举的使用。也许有人可以使用它...
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 Enum value)
{
foreach (object item in Enum.GetValues(typeof(T)))
{
yield return (T)item;
}
}
/// <summary>
/// Gets all items for an enum type.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value">The value.</param>
/// <returns></returns>
public static IEnumerable<T> GetAllItems<T>() where T : struct
{
foreach (object item in Enum.GetValues(typeof(T)))
{
yield return (T)item;
}
}
/// <summary>
/// Gets all combined items from an enum value.
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value">The value.</param>
/// <returns></returns>
/// <example>
/// Displays ValueA and ValueB.
/// <code>
/// EnumExample dummy = EnumExample.Combi;
/// foreach (var item in dummy.GetAllSelectedItems<EnumExample>())
/// {
/// Console.WriteLine(item);
/// }
/// </code>
/// </example>
public static IEnumerable<T> GetAllSelectedItems<T>(this Enum value)
{
int valueAsInt = Convert.ToInt32(value, CultureInfo.InvariantCulture);
foreach (object item in Enum.GetValues(typeof(T)))
{
int itemAsInt = Convert.ToInt32(item, CultureInfo.InvariantCulture);
if (itemAsInt == (valueAsInt & itemAsInt))
{
yield return (T)item;
}
}
}
/// <summary>
/// Determines whether the enum value contains a specific value.
/// </summary>
/// <param name="value">The value.</param>
/// <param name="request">The request.</param>
/// <returns>
/// <c>true</c> if value contains the specified value; otherwise, <c>false</c>.
/// </returns>
/// <example>
/// <code>
/// EnumExample dummy = EnumExample.Combi;
/// if (dummy.Contains<EnumExample>(EnumExample.ValueA))
/// {
/// Console.WriteLine("dummy contains EnumExample.ValueA");
/// }
/// </code>
/// </example>
public static bool Contains<T>(this Enum value, T request)
{
int valueAsInt = Convert.ToInt32(value, CultureInfo.InvariantCulture);
int requestAsInt = Convert.ToInt32(request, CultureInfo.InvariantCulture);
if (requestAsInt == (valueAsInt & requestAsInt))
{
return true;
}
return false;
}
}
The enum itself must be decorated with the FlagsAttribute:
枚举本身必须用FlagsAttribute装饰:
[Flags]
public enum EnumExample
{
ValueA = 1,
ValueB = 2,
ValueC = 4,
ValueD = 8,
Combi = ValueA | ValueB
}
回答by Ekevoo
Some versions of the .NET framework do not support Enum.GetValues
. Here's a good workaround from Ideas 2.0: Enum.GetValues in Compact Framework:
.NET 框架的某些版本不支持Enum.GetValues
. 这是Ideas 2.0的一个很好的解决方法: Enum.GetValues in Compact Framework:
public Enum[] GetValues(Enum enumeration)
{
FieldInfo[] fields = enumeration.GetType().GetFields(BindingFlags.Static | BindingFlags.Public);
Enum[] enumerations = new Enum[fields.Length];
for (var i = 0; i < fields.Length; i++)
enumerations[i] = (Enum) fields[i].GetValue(enumeration);
return enumerations;
}
As with any code that involves reflection, you should take steps to ensure it runs only once and results are cached.
与任何涉及反射的代码一样,您应该采取措施确保它只运行一次并缓存结果。
回答by Limited Atonement
foreach (Suit suit in Enum.GetValues(typeof(Suit))) { }
I've heard vague rumours that this is terifically slow. Anyone know? – Orion Edwards Oct 15 '08 at 1:31 7
foreach (Suit suit in Enum.GetValues(typeof(Suit))) { }
我听到模糊的谣言说这非常慢。有人知道吗?– 猎户座爱德华兹 08 年 10 月 15 日 1:31 7
I think caching the array would speed it up considerably. It looks like you're getting a new array (through reflection) every time. Rather:
我认为缓存数组会大大加快速度。看起来你每次都得到一个新数组(通过反射)。相当:
Array enums = Enum.GetValues(typeof(Suit));
foreach (Suit suitEnum in enums)
{
DoSomething(suitEnum);
}
That's at least a little faster, ja?
那至少快一点,ja?
回答by Mallox
My solution works in .NET Compact Framework(3.5) and supports type checking at compile time:
我的解决方案适用于.NET Compact Framework(3.5) 并支持编译时类型检查:
public static List<T> GetEnumValues<T>() where T : new() {
T valueType = new T();
return typeof(T).GetFields()
.Select(fieldInfo => (T)fieldInfo.GetValue(valueType))
.Distinct()
.ToList();
}
public static List<String> GetEnumNames<T>() {
return typeof (T).GetFields()
.Select(info => info.Name)
.Distinct()
.ToList();
}
- If anyone knows how to get rid of the
T valueType = new T()
, I'd be happy to see a solution.
- 如果有人知道如何摆脱
T valueType = new T()
,我很乐意看到解决方案。
A call would look like this:
一个调用看起来像这样:
List<MyEnum> result = Utils.GetEnumValues<MyEnum>();
回答by Aubrey Taylor
You won't get Enum.GetValues()
in Silverlight.
你不会得到Enum.GetValues()
在Silverlight中。
Original Blog Post by Einar Ingebrigtsen:
public class EnumHelper
{
public static T[] GetValues<T>()
{
Type enumType = typeof(T);
if (!enumType.IsEnum)
{
throw new ArgumentException("Type '" + enumType.Name + "' is not an enum");
}
List<T> values = new List<T>();
var fields = from field in enumType.GetFields()
where field.IsLiteral
select field;
foreach (FieldInfo field in fields)
{
object value = field.GetValue(enumType);
values.Add((T)value);
}
return values.ToArray();
}
public static object[] GetValues(Type enumType)
{
if (!enumType.IsEnum)
{
throw new ArgumentException("Type '" + enumType.Name + "' is not an enum");
}
List<object> values = new List<object>();
var fields = from field in enumType.GetFields()
where field.IsLiteral
select field;
foreach (FieldInfo field in fields)
{
object value = field.GetValue(enumType);
values.Add(value);
}
return values.ToArray();
}
}
回答by James
I think this is more efficient than other suggestions because GetValues()
is not called each time you have a loop. It is also more concise. And you get a compile-time error, not a runtime exception if Suit
is not an enum
.
我认为这比其他建议更有效,因为GetValues()
每次循环时都不会调用。它也更加简洁。如果Suit
不是enum
.
EnumLoop<Suit>.ForEach((suit) => {
DoSomethingWith(suit);
});
EnumLoop
has this completely generic definition:
EnumLoop
有这个完全通用的定义:
class EnumLoop<Key> where Key : struct, IConvertible {
static readonly Key[] arr = (Key[])Enum.GetValues(typeof(Key));
static internal void ForEach(Action<Key> act) {
for (int i = 0; i < arr.Length; i++) {
act(arr[i]);
}
}
}