如何在C#中拥有一组枚举值?

4

假设我有一个枚举:

namespace System.Windows.Forms
{
   public enum DialogResult { None, OK, Cancel, Abort, Retry, Ignore, Yes, No }
}

我想声明一个由这些枚举类型组成的“set”
ShowForm(Form frm, DialogResults allowedResults)

在其他语言中,您需要声明:
public DialogResults = set of DialogResult;

然后我可以使用

ShowForm(frm, DialogResult.OK | DialogResult.Retry);

C#有一个名为Flags的概念,伪代码如下:

[Flags]
public enum DialogResults { DialogResult.None, DialogResult.OK, DialogResult.Cancel, DialogResult.Abort, DialogResult.Retry, DialogResult.Ignore, DialogResult.Yes, DialogResult.No }

问题在于这不是真正的代码——Flags并没有告诉编译器创建一组标志。

  • 在一个情况下,类型只应允许一个值(DialogResult
  • 在另一个情况下,类型应该允许多个以上的值(DialogResults

我该如何拥有一个枚举类型的"集合"呢?

注意:我认为 C# 不支持此功能。如果确实如此,请直说,我的问题已得到解答。

注意:我认为 C# 语言不支持该功能,并不意味着它不支持该功能——我可能只是还没有找到它。


更新:另一个示例:

假设我有一个枚举:

public enum PatronTier 
{ 
    Gold = 1,      
    Platinum = 2,  
    Diamond = 3,   
    SevenStar = 7  //Yes, seven
}

我想声明一个由这些枚举类型组成的"set"
public Tournament
{
   public PatronTiers EligibleTiers { get; set; }
}

在其他语言中,你需要声明:
public PatronTiers = set of PatronTier;

然后我可以使用:

tournament.EligibleTiers = PatronTier.Gold | PatronTier.SevenStar;

C#有一个叫做Flags的概念,伪代码如下:

[Flags]
public enum PatronTiers { PatronTier.Gold, PatronTier.Platinum, PatronTier.Diamond, PatronTier.SevenStar }

问题在于它不是真正的代码。

我如何拥有一个枚举类型的“集合”?


1
HashSet<PatronTiers> 有问题吗? - John Saunders
3
公共的布尔类型婚姻是否有效。 - Dan J
您似乎正在尝试查找基于[Flags]的枚举类型和枚举类型的数组或列表(例如List<PatronTier>)之间的区域。在C#中没有这样的概念,您需要使用某种集合,或在枚举类型上使用[Flags]属性。 - Mike Marshall
2
你对同性婚姻有什么问题吗? - Jeff
1
@JeffN825 决定豁出去,将有问题的内容进行了编辑 :-) - Adam Houldsworth
显示剩余9条评论
3个回答

6
似乎你需要一个数组。在C#中有数组类型,但是没有直接等价于你的示例的编译器支持,最接近的可能是DialogResults[],它是一个DialogResults数组。
尝试提供一个允许的HashSetHashSet<T>实现了ISet<T>,对于方法签名来说,使用接口而不是具体类型通常是最好的选择。
ShowForm(Form frm, ISet<DialogResults> allowedResults);

接下来,您可以使用Contains测试项目:

if (allowedResults.Contains(DialogResults.OK))
{
}

有些无意义的替代方案:你可以使用Jon Skeet's Unconstrained Melody实现自己的Set<Enum>类型,这样从调用者的角度来看,语法更加优雅,并且能够更接近你的示例。


+1 但是方法参数应该是 ISet<DialogResults> 类型,以允许传递实现了 ISet<DialogResults> 接口的其他类。 - John Saunders
嗯,我有一个别名定义了类型(public class PrizeEligibleTiers : HashSet<PatronTier> {};)。如果要使用 ISet<> 版本的 PrizeEligibleTiers 别名,应该怎么写呢? - Ian Boyd
@IanBoyd:那不是别名,那是派生类型。由于HashSet<T>已经实现了ISet<T>,因此您不需要更改该派生类。 - John Saunders
啊,我明白你所说的“别名”是什么意思了。我喜欢的一个替代方案是在可能的情况下使用“var”代替显式类型名称。它大大有助于减少每当类型更改时需要更改的代码量。 - John Saunders
我在试图弄清楚为什么 HashSet<T> 没有实现 ISet<T>。然后我意识到,HashSet<T> 没有 实现 ISet<T>(http://msdn.microsoft.com/en-us/library/bb359438(v=VS.90).aspx)。 - Ian Boyd
显示剩余5条评论

2
我不认为你只是指使用这样的东西吧?
var DialogResults = Enum.GetValues(typeof(DialogResult));

如果您想要强类型,可以使用.Select(dr => (DialogResult)dr).ToArray()

如果您想要强类型化,请使用.Cast<DialogResult>().ToArray() - Scott Rippey

1
我认为你想要这样的东西:
foreach (var item in System.Enum.GetValues(typeof(PatronTier)))
{
    Console.WriteLine(item);
}

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