如何在C#中枚举枚举?
例如,以下代码无法编译:
public enum Suit
{
Spades,
Hearts,
Clubs,
Diamonds
}
public void EnumerateAllSuitsDemoMethod()
{
foreach (Suit suit in Suit)
{
DoSomething(suit);
}
}
它给出了以下编译时错误:
“Suit”是“type”,但与“variable”类似
它在第二个Suit关键字上失败。
我不认为这更好,甚至更好。我只是在陈述另一种解决方案。
如果枚举值的范围严格从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;
}
}
但这不是严格的枚举,只是循环。第二种方法比任何其他方法都快得多。。。
我做了一些扩展以方便枚举的使用。也许有人可以使用它。。。
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
}
三种方式:
Enum.GetValues(类型)//自.NET 1.1起,不在Silverlight或.NET Compact Framework中type.GetEnumValues()//仅适用于.NET 4及更高版本type.GetFields()。其中(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();
// Or
Enum.GetValues(typeof(Suit)); // Pretty consistent style
如果性能很重要,也可以使用某种缓存,但我不认为这是一个问题。
public static class Enum<T> where T : struct, IComparable, IFormattable, IConvertible
{
// Lazily loaded
static 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)));
}
}