枚举类型中是否可以遍历每个选项?

5

可能是重复问题:
如何枚举枚举?

所以我的代码像这样:

enum Decision
{
  DecisionA,
  DecisionB,
  ...
}

public void DoStuff(Decision d)
{
  switch(d)
  {
    case Decision.DecisionA:
    ....
    ...
  }
}

基本上,无论做出何种决策,DoStuff都会执行相同的操作,但是这些决策可以使其更加优化(更快或其他)。

现在,我想为DoStuff实现单元测试。通过像new Decision [] {DecisionA, DecisionB, ...};这样拥有一个数组来测试所有决策是否正常运行非常容易。然而,如果我添加了一个决策,我就必须回去手动将其添加到单元测试中。

是否可以仅访问由enum指定的所有可能选项?例如,像这样:

foreach(var d in Decision.Options)
{
  //d will be DecisionA, and then DecisionB, etc etc
}
3个回答

10

你可以使用Enum.GetValues,但个人不是很喜欢它。你需要强制类型转换(例如通过指定迭代变量类型),并通过typeof提供类型:

foreach (Decision decision in Enum.GetValues(typeof(Decision)))
{
}

我更喜欢我在Unconstrained Melody中提供的选项 - 这是一个小库,提供了对枚举和委托的扩展方法:

foreach (var decision in Enums.GetValues<Decision>())
{
}

这是:

  • 返回类型安全(它返回一个IList<T>
  • 类型参数安全(类型必须是枚举)
  • 更加高效,因为它可以重复使用相同的只读列表进行多次调用

当然,这意味着需要使用额外的库...如果你只需要进行单个调用,则可能不值得使用,但如果你需要处理大量的枚举类型,你可能会发现其他功能非常有用。


嗯,我想现在就用丑陋的版本,特别是因为它只是用于单元测试。 - Earlz
如何枚举一个枚举类型?这是最受欢迎的问题之一,下面是答案。 - jparthj
@jparthj 啊,那这就是一个重复的了。我会投票关闭。 - Earlz

3

1

Jon的回答给了你枚举,这里还有一些其他的随机事情...

对于测试而言,可能更好的方法是采用另一种方式 - 确保值列表 (Enum.GetValues) 与测试中硬编码的列表相匹配。在添加新值时使测试失败,然后更新测试以对新值执行某些明智的操作(如果测试不同案例实际上需要不同,则非常有用)。

看待它的另一种方式 - switch 和一系列的 if 不是控制代码流的最佳结构。你可以使用多态或简单字典进行重构,以使其更易于测试/可扩展 (有几个问题类似于 如何重构这个巨大的 switch 语句? )。


我不使用枚举的问题在于有时“决策”是基于随机数生成器的。将int强制转换为枚举很容易。但是,将int转换为调用另一个函数则更加麻烦。 - Earlz
1
@Earlz,如果这样的话Dictionary<int, Func<RType>>可能会起作用……如果它能让你的代码更易读的话。 - Alexei Levenkov

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接