【问题标题】:How to have a set of enumeration values in C#?如何在 C# 中拥有一组枚举值?
【发布时间】:2011-12-15 16:42:25
【问题描述】:

假设我have an enumeration:

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)

我怎样才能有一个枚举类型的“set”

注意:我认为这在 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 }

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

我怎样才能有一个枚举类型的“set”

【问题讨论】:

  • HashSet<PatronTiers>有问题吗?
  • public Boolean MarriageValid 哎呀,没碰那个例子。 :P
  • 您似乎试图在基于 [Flags] 的枚举和枚举类型的数组或列表(例如 List)之间找到一个区域。 C# 中没有这样的概念,您需要使用某种集合,或者在枚举中使用 [Flags] 属性。
  • 你对同性婚姻有什么问题吗?
  • @JeffN825 咬紧牙关,编辑了有问题的东西 :-)

标签: c# enums set


【解决方案1】:

看起来你想要一堆东西。 C# 中有数组类型,但就编译器支持而言,没有什么直接与您的示例等效,最接近的可能是 DialogResults[]DialogResults 的数组。

尝试提供HashSet 您允许的项目。 HashSet<T> 实现 ISet<T>,通常最好针对接口而不是具体类型,尤其是对于方法签名:

ShowForm(Form frm, ISet<DialogResults> allowedResults);

然后你可以使用Contains来测试项目:

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

有点毫无意义的替代方案:您始终可以使用 Jon Skeet's Unconstrained Melody 实现自己的 Set&lt;Enum&gt; 类型,以便从调用者的角度为您提供更好的语法,并更接近您的示例。

【讨论】:

  • +1 但方法参数的类型应为ISet&lt;DialogResults&gt; 以允许传递实现ISet&lt;DialogResults&gt; 的其他类。
  • @JohnSaunders 甚至没有意识到有一个ISet&lt;&gt; 接口,更新了我的答案以适应。
  • 嗯。我有一个定义类型的别名(public class PrizeEligibleTiers : HashSet&lt;PatronTier&gt; {};)他的PrizeEligibleTiers 别名的ISet&lt;&gt; 版本是什么?
  • @IanBoyd:这不是别名,而是派生类型。由于HashSet&lt;T&gt; 已经实现了ISet&lt;T&gt;,因此您无需更改该派生类。
  • @JohnSaunders 但是我仍然想要一个别名,这样当我更改全局使用的类型时我就不必更新源代码(即,不管 PrizeEligibleTiers 是什么,只要它是) (因为我已经有使用PrizeEligibleTiers 的代码并且该类型可以保留该名称,所以突出意味着其他)
【解决方案2】:

我不认为你的意思是使用这样的东西?

var DialogResults = Enum.GetValues(typeof(DialogResult));

如果您希望它是强类型的,请使用 .Select(dr =&gt; (DialogResult)dr).ToArray()

【讨论】:

  • 如果你希望它是强类型的,使用.Cast&lt;DialogResult&gt;().ToArray()
【解决方案3】:

我想你想要这样的东西:

foreach (var item in System.Enum.GetValues(typeof(PatronTier)))
{
    Console.WriteLine(item);
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-04-18
    • 2014-04-06
    • 2019-07-18
    • 1970-01-01
    • 1970-01-01
    • 2015-02-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多