咨询区
Peter Mortensen:
如何使用 C# 迭代 enum ?
下面的代码会编译失败,错误信息: 'Suit' is a 'type' but is used like a 'variable'
public enum Suit
{Spades,Hearts,Clubs,Diamonds
}public void EnumerateAllSuitsDemoMethod()
{foreach (Suit suit in Suit){DoSomething(suit);}
}
回答区
Ian Boyd:
可以这么实现。
foreach (Suit suit in (Suit[]) Enum.GetValues(typeof(Suit)))
{
}
注意:转成 Suit[]
不是必须的,但会有 0.5ns 的提速。
Jap:
我给 enum 实现了一些便捷的扩展,我想应该有朋友用的上。
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;}
}
不过 enum 必须打上 FlagsAttribute
标记。
[Flags]
public enum EnumExample
{ValueA = 1,ValueB = 2,ValueC = 4,ValueD = 8,Combi = ValueA | ValueB
}
Mallox:
Enum.GetValues
在 .NET Compact Framework 版本中是不支持的,需要用反射实现。
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();
}
调用方式如下:
List<MyEnum> result = Utils.GetEnumValues<MyEnum>();
点评区
相信有很有朋友都遇到过迭代 enum 的需求,比如说将 enum 绑定到 下拉框
中,不过很遗憾的是,FCL 提供的 Enum 太弱了,不过在 .NET 5 中 Enum 得到了加强。
在 .NET5 中直接修改如下即可。
var suitsList = Enum.GetValues<Suits>();
原文链接:https://stackoverflow.com/questions/105372/how-to-enumerate-an-enum