如何枚举枚举?

如何在C#中枚举enum

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

public enum Suit{Spades,Hearts,Clubs,Diamonds}
public void EnumerateAllSuitsDemoMethod(){foreach (Suit suit in Suit){DoSomething(suit);}}

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

“西装”是一个“类型”,但像“变量”一样使用

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

970468 次浏览

我想你可以用

Enum.GetNames(Suit)
foreach (Suit suit in (Suit[]) Enum.GetValues(typeof(Suit))){}

说明:对(Suit[])的转换不是严格必要的,但它确实使代码快了0.5纳秒

在我看来,您真的想打印出每个枚举的名称,而不是值。在这种情况下,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);}}

顺便说一句,递增值不是枚举枚举值的好方法。您应该这样做。

我将使用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());}}
public void PrintAllSuits(){foreach(string suit in Enum.GetNames(typeof(Suits))){Console.WriteLine(suit);}}

我做了一些扩展以便于枚举使用。也许有人可以使用它…

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;}}

枚举本身必须用标志属性装饰:

[Flags]public enum EnumExample{ValueA = 1,ValueB = 2,ValueC = 4,ValueD = 8,Combi = ValueA | ValueB}

某些版本的. NET框架不支持Enum.GetValues。以下是想法2.0:紧凑型框架中的Enums. GetValue的一个很好的解决方法:

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;}

与任何涉及反射的代码一样,您应该采取措施确保它只运行一次并缓存结果。

foreach (Suit suit in Enum.GetValues(typeof(Suit))) { }

我听到一些谣言说非常慢。有人知道吗?-猎户座爱德华兹10月15日'08在1:31 7

我认为缓存数组会大大加快速度。看起来你每次都得到一个新数组(通过反射)。相反:

Array enums = Enum.GetValues(typeof(Suit));foreach (Suit suitEnum in enums){DoSomething(suitEnum);}

这样至少快一点,对吧?

我的解决方案适用于. 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();}
  • 如果有人知道如何摆脱T valueType = new T(),我很乐意看到一个解决方案。

调用看起来像这样:

List<MyEnum> result = Utils.GetEnumValues<MyEnum>();

你不会在Silverlight中得到Enum.GetValues()

原文作者:EinarIngebrigtsen

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.IsLiteralselect 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.IsLiteralselect field;
foreach (FieldInfo field in fields){object value = field.GetValue(enumType);values.Add(value);}
return values.ToArray();}}

我认为这比其他建议更有效,因为每次有循环时都不会调用GetValues()。它也更简洁。如果Suit不是enum,你会得到一个编译时错误,而不是运行时异常。

EnumLoop<Suit>.ForEach((suit) => {DoSomethingWith(suit);});

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]);}}}

我使用ToString(),然后在标志中拆分和解析吐数组。

[Flags]public enum ABC {a = 1,b = 2,c = 4};
public IEnumerable<ABC> Getselected (ABC flags){var values = flags.ToString().Split(',');var enums = values.Select(x => (ABC)Enum.Parse(typeof(ABC), x.Trim()));return enums;}
ABC temp= ABC.a | ABC.b;var list = getSelected (temp);foreach (var item in list){Console.WriteLine(item.ToString() + " ID=" + (int)item);}

以下是为DDL创建选择选项的工作示例:

var resman = ViewModelResources.TimeFrame.ResourceManager;
ViewBag.TimeFrames = from MapOverlayTimeFrames timeFramein Enum.GetValues(typeof(MapOverlayTimeFrames))select new SelectListItem{Value = timeFrame.ToString(),Text = resman.GetString(timeFrame.ToString()) ?? timeFrame.ToString()};

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

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

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

使用Cast<T>

var suits = Enum.GetValues(typeof(Suit)).Cast<Suit>();

你走了,IEnumerable<Suit>

通过组合上面的答案,我拼凑了一个非常简单的扩展:

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

三种方式:

  1. Enum.GetValues(type)//从. NET 1.1开始,不在Silverlight或. NET Compact Framework中
  2. type.GetEnumValues()//仅适用于. NET 4及更高版本
  3. type.GetFields().Where(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();
// OrEnum.GetValues(typeof(Suit)); // Pretty consistent style

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

public static class Enum<T> where T : struct, IComparable, IFormattable, IConvertible{// Lazily loadedstatic 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)));}}

如果您需要在构建和运行时检查速度和类型,则此helper方法比使用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>,但这在这里什么也买不到。

foreach (Suit suit in Enum.GetValues(typeof(Suit))){}

(当前接受的答案有一个我不认为的演员阵容(虽然我可能是错的)

我知道这有点混乱,但如果你是单行的粉丝,这里有一个:

((Suit[])Enum.GetValues(typeof(Suit))).ToList().ForEach(i => DoSomething(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>();

这个问题出现在“C#一步一步2013”的第10章

作者使用双for循环遍历一对枚举器(以创建完整的一副牌):

class Pack{public const int NumSuits = 4;public const int CardsPerSuit = 13;private PlayingCard[,] cardPack;
public Pack(){this.cardPack = new PlayingCard[NumSuits, CardsPerSuit];for (Suit suit = Suit.Clubs; suit <= Suit.Spades; suit++){for (Value value = Value.Two; value <= Value.Ace; value++){cardPack[(int)suit, (int)value] = new PlayingCard(suit, value);}}}}

在这种情况下,SuitValue都是枚举:

enum Suit { Clubs, Diamonds, Hearts, Spades }enum Value { Two, Three, Four, Five, Six, Seven, Eight, Nine, Ten, Jack, Queen, King, Ace}

PlayingCard是一个定义了SuitValue的卡片对象:

class PlayingCard{private readonly Suit suit;private readonly Value value;
public PlayingCard(Suit s, Value v){this.suit = s;this.value = v;}}

如果您知道类型将是enum,但您在编译时不知道确切的类型是什么怎么办?

public class EnumHelper{public static IEnumerable<T> GetValues<T>(){return Enum.GetValues(typeof(T)).Cast<T>();}
public static IEnumerable getListOfEnum(Type type){MethodInfo getValuesMethod = typeof(EnumHelper).GetMethod("GetValues").MakeGenericMethod(type);return (IEnumerable)getValuesMethod.Invoke(null, null);}}

方法getListOfEnum使用反射来获取任何枚举类型并返回所有枚举值的IEnumerable

用法:

Type myType = someEnumValue.GetType();
IEnumerable resultEnumerable = getListOfEnum(myType);
foreach (var item in resultEnumerable){Console.WriteLine(String.Format("Item: {0} Value: {1}",item.ToString(),(int)item));}

有两种方法可以迭代Enum

1. var values =  Enum.GetValues(typeof(myenum))2. var values =  Enum.GetNames(typeof(myenum))

第一个将以**object**s数组的形式为您提供值,第二个将以**String**s数组的形式为您提供值。

foreach循环中使用它,如下所示:

foreach(var value in values){// Do operations here}

您还可以使用反射直接绑定到枚举的公共静态成员:

typeof(Suit).GetMembers(BindingFlags.Public | BindingFlags.Static).ToList().ForEach(x => DoSomething(x.Name));

将方法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 methodvar foos = GetValues<Suit>();foreach (var foo in foos){// Do something}}

enum类型被称为“枚举类型”,不是因为它们是“枚举”值的容器(它们不是),而是因为它们是由枚举定义的该类型变量的可能值。

(实际上,这比这要复杂一点-枚举类型被认为具有“基础”整数类型,这意味着每个枚举值对应于一个整数值(这通常是隐式的,但可以手动指定)。C#的设计方式是让您可以将该类型的任何整数填充到枚举变量中,即使它不是“命名”值。)

System. Enums. GetNames方法可用于检索字符串数组,这些字符串是枚举值的名称,顾名思义。

编辑:应该建议使用System. E num. Get值方法。

要从枚举中获取int列表,请使用以下命令。它有效!

List<int> listEnumValues = new List<int>();YourEnumType[] myEnumMembers = (YourEnumType[])Enum.GetValues(typeof(YourEnumType));foreach ( YourEnumType enumMember in myEnumMembers){listEnumValues.Add(enumMember.GetHashCode());}

如果您有:

enum Suit{Spades,Hearts,Clubs,Diamonds}

这个:

foreach (var e in Enum.GetValues(typeof(Suit))){Console.WriteLine(e.ToString() + " = " + (int)e);}

将输出:

Spades = 0Hearts = 1Clubs = 2Diamonds = 3

LINQ通用方式:

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

用法:

        var enums = ToList<Enum>();

新的. NET 5解决方案:

. NET 5引入了#0的新通用版本方法:

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

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

Foreach循环中的用法:

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

如果您只需要枚举名称作为字符串,您可以使用泛型GetNames方法:

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

我认为这有助于你尝试一下。

public class Program{
public static List<T> GetEnamList<T>(){var enums = Enum.GetValues(typeof(T)).Cast<T>().Select(v => v).ToList();return enums;}private void LoadEnumList(){List<DayofWeek> dayofweeks = GetEnamList<DayofWeek>();
foreach (var item in dayofweeks){dayofweeks.Add(item);}}}
public enum DayofWeek{Monday,Tuesday,Wensday,Thursday,Friday,Sturday,Sunday}

当你有一个像这样的枚举

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();}

一个简单的Enumm. GetNames(枚举类型)应该可以工作