我如何枚举枚举?
时间:2020-03-06 14:27:44 来源:igfitidea点击:
我们如何在C#中枚举一个"枚举"?
例如。以下代码无法编译:
public enum Suit { Spades, Hearts, Clubs, Diamonds } public void EnumerateAllSuitsDemoMethod() { foreach (Suit suit in Suit) { DoSomething(suit); } }
并给出以下编译时错误:
'Suit' is a 'type' but is used like a 'variable'
它在第二个关键字" Suit"上失败。
解决方案
我想你可以用
Enum.GetNames(Suit)
foreach (Suit suit in (Suit[]) Enum.GetValues(typeof(Suit))) { }
在我看来,我们确实想打印出每个枚举的名称,而不是值。在这种情况下," 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; } }
枚举本身必须用FlagsAttribute装饰
[Flags] public enum EnumExample { ValueA = 1, ValueB = 2, ValueC = 4, ValueD = 8, Combi = ValueA | ValueB }
.NET框架的某些版本不支持Enum.GetValues
。这是Ideas 2.0的一个很好的解决方法:Compact Framework中的Enum.GetValues:
public List<Enum> GetValues(Enum enumeration) { List<Enum> enumerations = new List<Enum>(); foreach (FieldInfo fieldInfo in enumeration.GetType().GetFields( BindingFlags.Static | BindingFlags.Public)) { enumerations.Add((Enum)fieldInfo.GetValue(enumeration)); } return enumerations; }
与任何涉及反射的代码一样,我们应采取步骤确保其仅运行一次并缓存结果。
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
我认为缓存阵列将大大加快速度。看起来我们每次都在获取一个新数组(通过反射)。相当:
Array enums = Enum.GetValues(typeof(Suit)); foreach (Suit suitEnum in enums) { DoSomething(suitEnum); }
至少快一点,对吗?
只需添加我的解决方案即可在紧凑框架(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()
。
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(); } }