我如何枚举枚举?
时间: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();
}
}

