如何枚举一个枚举

今天药忘吃喽~ 2024-03-31 17:45 307阅读 0赞

问题描述:

如何在 C# 中枚举 enum?

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

  1. public enum Suit
  2. {
  3. Spades,
  4. Hearts,
  5. Clubs,
  6. Diamonds
  7. }
  8. public void EnumerateAllSuitsDemoMethod()
  9. {
  10. foreach (Suit suit in Suit)
  11. {
  12. DoSomething(suit);
  13. }
  14. }

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

“西装”是一种“类型”,但用作“变量”

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

解决方案1:

huntsbot.com洞察每一个产品背后的需求与收益,从而捕获灵感

  1. foreach (Suit suit in (Suit[]) Enum.GetValues(typeof(Suit)))
  2. {
  3. }

注意:强制转换为 (Suit[]) 并不是绝对必要的,but it does make the code 0.5 ns faster。

如果枚举器列表中有重复值,这将不起作用。

我只想指出,不幸的是,这在 silverlight 中不起作用,因为 silverlight 库不包含 enum.GetValues。在这种情况下,您必须使用反射。

@Jessy 这确实适用于像 enum E {A = 0, B = 0} 这样的重复情况。 Enum.GetValues 导致返回两个值,尽管它们是相同的。 E.A == E.B 为真,因此没有区别。如果您想要单独的名称,那么您应该查找 Enum.GetNames。

然后,如果您的枚举中有重复项/同义词,并且您想要其他行为,您可以使用 Linq 的 Distinct 扩展(从 .NET 3.5 开始),所以 foreach (var suit in ((Suit[])Enum.GetValues(typeof(Suit))).Distinct()) { }。

我错误地尝试使用 var 作为类型。编译器会将变量设为 Object 而不是枚举。明确列出枚举类型。

解决方案2:

huntsbot.com – 高效赚钱,自由工作

在我看来,您真的想打印出每个枚举的名称,而不是值。在这种情况下,Enum.GetNames() 似乎是正确的方法。

  1. public enum Suits
  2. {
  3. Spades,
  4. Hearts,
  5. Clubs,
  6. Diamonds,
  7. NumSuits
  8. }
  9. public void PrintAllSuits()
  10. {
  11. foreach (string name in Enum.GetNames(typeof(Suits)))
  12. {
  13. System.Console.WriteLine(name);
  14. }
  15. }

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

我会改用 Enum.GetValues(typeof(Suit))。

  1. public enum Suits
  2. {
  3. Spades,
  4. Hearts,
  5. Clubs,
  6. Diamonds,
  7. NumSuits
  8. }
  9. public void PrintAllSuits()
  10. {
  11. foreach (var suit in Enum.GetValues(typeof(Suits)))
  12. {
  13. System.Console.WriteLine(suit.ToString());
  14. }
  15. }

此处的 VB 语法:link

我对您的版本进行了以下小改动:Enum.GetValues(typeof(Suits)).OfType().ToArray()。在这种情况下,我可以迭代 Suits 枚举项的数组,而不是字符串。

@Barabas 为什么不只做 Suits suit in Enum.GetValues(typeof(Suits)) ?

解决方案3:

打造属于自己的副业,开启自由职业之旅,从huntsbot.com开始!

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

  1. public static class EnumExtensions
  2. {
  3. ///
  4. /// Gets all items for an enum value.
  5. ///
  6. ///
  7. /// The value.
  8. ///
  9. public static IEnumerable GetAllItems(this Enum value)
  10. {
  11. foreach (object item in Enum.GetValues(typeof(T)))
  12. {
  13. yield return (T)item;
  14. }
  15. }
  16. ///
  17. /// Gets all items for an enum type.
  18. ///
  19. ///
  20. /// The value.
  21. ///
  22. public static IEnumerable GetAllItems() where T : struct
  23. {
  24. foreach (object item in Enum.GetValues(typeof(T)))
  25. {
  26. yield return (T)item;
  27. }
  28. }
  29. ///
  30. /// Gets all combined items from an enum value.
  31. ///
  32. ///
  33. /// The value.
  34. ///
  35. ///
  36. /// Displays ValueA and ValueB.
  37. ///
  38. /// EnumExample dummy = EnumExample.Combi;
  39. /// foreach (var item in dummy.GetAllSelectedItems())
  40. /// {
  41. /// Console.WriteLine(item);
  42. /// }
  43. ///
  44. ///
  45. public static IEnumerable GetAllSelectedItems(this Enum value)
  46. {
  47. int valueAsInt = Convert.ToInt32(value, CultureInfo.InvariantCulture);
  48. foreach (object item in Enum.GetValues(typeof(T)))
  49. {
  50. int itemAsInt = Convert.ToInt32(item, CultureInfo.InvariantCulture);
  51. if (itemAsInt == (valueAsInt & itemAsInt))
  52. {
  53. yield return (T)item;
  54. }
  55. }
  56. }
  57. ///
  58. /// Determines whether the enum value contains a specific value.
  59. ///
  60. /// The value.
  61. /// The request.
  62. ///
  63. /// true if value contains the specified value; otherwise, false.
  64. ///
  65. ///
  66. ///
  67. /// EnumExample dummy = EnumExample.Combi;
  68. /// if (dummy.Contains(EnumExample.ValueA))
  69. /// {
  70. /// Console.WriteLine("dummy contains EnumExample.ValueA");
  71. /// }
  72. ///
  73. ///
  74. public static bool Contains(this Enum value, T request)
  75. {
  76. int valueAsInt = Convert.ToInt32(value, CultureInfo.InvariantCulture);
  77. int requestAsInt = Convert.ToInt32(request, CultureInfo.InvariantCulture);
  78. if (requestAsInt == (valueAsInt & requestAsInt))
  79. {
  80. return true;
  81. }
  82. return false;
  83. }
  84. }

枚举本身必须用 FlagsAttribute 装饰:

  1. [Flags]
  2. public enum EnumExample
  3. {
  4. ValueA = 1,
  5. ValueB = 2,
  6. ValueC = 4,
  7. ValueD = 8,
  8. Combi = ValueA | ValueB
  9. }

用于第一种扩展方法的一个衬垫;它不再懒惰了。返回 Enum.GetValues(typeof(T)).Cast();

或者,您也可以使用 OfType:Enum.GetValues(typeof(T)).OfType()。太糟糕了,没有 GetValues() 的通用版本,那么它会更加光滑。

也许有人可以展示如何使用这些扩展?编译器不会在枚举 EnumExample 上显示扩展方法。

+1 可重用代码:示例 - 将这些扩展方法保存在库中并引用它 [Flags]public enum mytypes{name1, name2 };列表<字符串> myTypeNames = mytypes.GetAllItems();

从 C# 7.3 (Visual Studio 2017 ≥ v15.7) 开始,可以使用 where T: Enum

解决方案4:

huntsbot.com洞察每一个产品背后的需求与收益,从而捕获灵感

.NET 框架的某些版本不支持 Enum.GetValues。以下是来自 Ideas 2.0: Enum.GetValues in Compact Framework 的一个很好的解决方法:

  1. public Enum[] GetValues(Enum enumeration)
  2. {
  3. FieldInfo[] fields = enumeration.GetType().GetFields(BindingFlags.Static | BindingFlags.Public);
  4. Enum[] enumerations = new Enum[fields.Length];
  5. for (var i = 0; i < fields.Length; i++)
  6. enumerations[i] = (Enum) fields[i].GetValue(enumeration);
  7. return enumerations;
  8. }

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

为什么不在这里使用 yield 关键字来实例化一个列表呢?

或更短:return type.GetFields().Where(x => x.IsLiteral).Select(x => x.GetValue(null)).Cast();

@nawfal:Linq 不可用 .Net CF 2.0。

解决方案5:

huntsbot.com精选全球7大洲远程工作机会,涵盖各领域,帮助想要远程工作的数字游民们能更精准、更高效的找到对方。

使用 Cast:

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

你去吧,IEnumerable。

huntsbot.com洞察每一个产品背后的需求与收益,从而捕获灵感

这也适用于 from 子句和 foreach 标头声明符。

'cast' api 需要 System.Linq。我只是缺少演员。

解决方案6:

一个优秀的自由职业者,应该有对需求敏感和精准需求捕获的能力,而huntsbot.com提供了这个机会

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

  1. EnumLoop.ForEach((suit) => {
  2. DoSomethingWith(suit);
  3. });

EnumLoop 有这个完全通用的定义:

  1. class EnumLoop where Key : struct, IConvertible {
  2. static readonly Key[] arr = (Key[])Enum.GetValues(typeof(Key));
  3. static internal void ForEach(Action act) {
  4. for (int i = 0; i < arr.Length; i++) {
  5. act(arr[i]);
  6. }
  7. }
  8. }

小心使用这样的泛型。如果您尝试将 EnumLoop 与某种非枚举类型一起使用,它会编译得很好,但会在运行时引发异常。

谢谢你。运行时异常实际上会与此页面上的其他答案一起发生......除了这个,因为我添加了“where Key : struct, IConvertible”,因此在大多数情况下都会出现编译时错误。

不,GetValues() 在 foreach 中只调用一次。

詹姆斯,我会劝阻你的课程,因为聪明写得很好,但在许多人将维护和更新的生产代码中,聪明是额外的工作。如果它节省了大量资金或将被大量使用——所以节省的资金很大,人们会熟悉它——这是值得的,但在大多数情况下,它会减慢人们阅读和更新代码的速度,并引入一个可能的未来的源错误。代码越少越好:) 复杂性越低越好。

@GrantM 为什么?这段代码既不复杂,也非常短。最重要的是,按照他的示例,编写一次类将允许使用更短的代码迭代。这非常干净,如果您无法更新该代码,则可能无法更新任何公司代码。

解决方案7:

huntsbot.com聚合了超过10+全球外包任务平台的外包需求,寻找外包任务与机会变的简单与高效。

您不会在 Silverlight 中获得 Enum.GetValues()。

Original Blog Post by Einar Ingebrigtsen:

  1. public class EnumHelper
  2. {
  3. public static T[] GetValues()
  4. {
  5. Type enumType = typeof(T);
  6. if (!enumType.IsEnum)
  7. {
  8. throw new ArgumentException("Type '" + enumType.Name + "' is not an enum");
  9. }
  10. List values = new List();
  11. var fields = from field in enumType.GetFields()
  12. where field.IsLiteral
  13. select field;
  14. foreach (FieldInfo field in fields)
  15. {
  16. object value = field.GetValue(enumType);
  17. values.Add((T)value);
  18. }
  19. return values.ToArray();
  20. }
  21. public static object[] GetValues(Type enumType)
  22. {
  23. if (!enumType.IsEnum)
  24. {
  25. throw new ArgumentException("Type '" + enumType.Name + "' is not an enum");
  26. }
  27. List values = new List();
  28. var fields = from field in enumType.GetFields()
  29. where field.IsLiteral
  30. select field;
  31. foreach (FieldInfo field in fields)
  32. {
  33. object value = field.GetValue(enumType);
  34. values.Add(value);
  35. }
  36. return values.ToArray();
  37. }
  38. }

我正在使用 .NET framework 4.0 & silverlight enum.getvalues 工作,我使用的代码是 ---> enum.GetValues(typeof(enum))

从 C# 7.3 (Visual Studio 2017 ≥ v15.7) 开始,可以使用 where T: Enum

解决方案8:

保持自己快人一步,享受全网独家提供的一站式外包任务、远程工作、创意产品订阅服务–huntsbot.com

新的 .NET 5 解决方案:

.NET 5 引入了一个 new generic version for the GetValues 方法:

  1. Suit[] suitValues = Enum.GetValues();

这是迄今为止最方便的方法。

foreach 循环中的用法:

  1. foreach (Suit suit in Enum.GetValues())
  2. {
  3. }

并获取枚举名称:

  1. string[] suitNames = Enum.GetNames();

解决方案9:

HuntsBot周刊–不定时分享成功产品案例,学习他们如何成功建立自己的副业–huntsbot.com

我的解决方案适用于 .NET Compact Framework (3.5) 并支持在编译时进行类型检查:

  1. public static List GetEnumValues() where T : new() {
  2. T valueType = new T();
  3. return typeof(T).GetFields()
  4. .Select(fieldInfo => (T)fieldInfo.GetValue(valueType))
  5. .Distinct()
  6. .ToList();
  7. }
  8. public static List GetEnumNames() {
  9. return typeof (T).GetFields()
  10. .Select(info => info.Name)
  11. .Distinct()
  12. .ToList();
  13. }

如果有人知道如何摆脱 T valueType = new T(),我很乐意看到解决方案。

调用如下所示:

  1. List result = Utils.GetEnumValues();

使用 T valueType = default(T) 怎么样?

太好了,我什至不知道那个关键字。总是很高兴学习新东西。谢谢!它总是返回对同一个对象的引用,还是每次调用默认语句时都会创建一个新实例?到目前为止,我还没有在网上找到任何关于此的内容,但如果它每次都创建一个新实例,那么它有点违背了我正在寻找的目的(有一个单行 ^^)。

这不会为枚举的每次迭代创建一个新实例吗?

-1 表示“在编译时支持类型检查:”。什么类型检查?这适用于任何 new() T。此外,您根本不需要 new T(),您可以只选择静态字段并执行 .GetValue(null)。见奥布里的回答。

从 C# 7.3 (Visual Studio 2017 ≥ v15.7) 开始,可以使用 where T: Enum

解决方案10:

保持自己快人一步,享受全网独家提供的一站式外包任务、远程工作、创意产品订阅服务–huntsbot.com

我认为你可以使用

  1. Enum.GetNames(Suit)

解决方案11:

huntsbot.com全球7大洲远程工作机会,探索不一样的工作方式

  1. public void PrintAllSuits()
  2. {
  3. foreach(string suit in Enum.GetNames(typeof(Suits)))
  4. {
  5. Console.WriteLine(suit);
  6. }
  7. }

枚举一个字符串,不要忘记将这些东西转换回枚举值,以便枚举可以枚举。

我从您的编辑中看到您想要实际操作枚举本身,上面的代码解决了您的原始帖子。

原文链接:https://www.huntsbot.com/qa/aL7l/how-to-enumerate-an-enum?lang=zh_CN

huntsbot.com – 高效赚钱,自由工作

发表评论

表情:
评论列表 (有 0 条评论,307人围观)

还没有评论,来说两句吧...

相关阅读

    相关

    在学C++和做一些实践的时候发现,枚举类型有时候是必要的。 有时我们希望某些常量只在类中有效。由于\define定义的宏常量是全局的,不能达到目的,于是想当然地觉得应该用co

    相关

    当定义一个枚举时,编译器就会创建一个扩展java.lang.Enum类的类定义。这个类是java.lang.Object的一个直接后代。但与普通类不同的是,枚举具有以下属性:

    相关

      在第一次学习面向对象编程时,我记得最深的一句话就是“万物皆对象”。于是我一直秉承着这个思想努力的学习着JAVA,直到学习到枚举(Enum)时,看着它颇为奇怪的语法……我一直

    相关

    JDK1.5之前需要自定义枚举类 JDK 1.5 新增的 enum 关键字用于定义枚举类 若枚举只有一个成员, 则可以作为一种单例模式的实现方式 枚举类对象的属性

    相关

    枚举 什么是枚举? 枚举指的是在一定范围内取值,这个值必须是枚举类型中的任意一个,而且只能够取其中的一个 枚举的特点: 1.枚举的本质就是一个Java类

    相关

                                       枚举(穷举,暴力求解) 一.基本思想         对问题变量可能解集合的每一个元素,根据问题给出