4

Assume i have an enumeration:

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

i want to declare a "set" made up of these enumerated types

ShowForm(Form frm, DialogResults allowedResults)

In other languages you would declare:

public DialogResults = set of DialogResult;

And then i can use

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

C# has the notion of Flags, pseudocode:

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

problem with that it's not real code - Flags does not instruct the compiler to create a set of flags.

  • in one case the type should only allow one value (DialogResult)
  • in another case the type should allow multiple values of above (DialogResults)

How can i have a "set" of enumerated types?

Note: i assume it's not possible in C#. If that's the answer: it's okay to say so - the question is answered.

Note: Just because i believe C# language doesn't have the feature doesn't mean it doesn't have the feature - i may just not have found it yet.


Update: another example:

Assume i have an enumeration:

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

i want to declare a "set" made up of these enumerated types

public Tournament
{
   public PatronTiers EligibleTiers { get; set; }
}

In other languages you would declare:

public PatronTiers = set of PatronTier;

And then i can use:

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

C# has the notion of Flags, pseudocode:

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

problem with that it's not real code.

How can i have a "set" of enumerated types?

Ian Boyd
  • 246,734
  • 253
  • 869
  • 1,219
  • 1
    Is there a problem with `HashSet`? – John Saunders Dec 15 '11 at 16:45
  • 3
    `public Boolean MarriageValid` Hoo boy, not touching that example. :P – Dan J Dec 15 '11 at 16:45
  • You seem to be trying to find an area between a [Flags]-based enumeration and an array or list of the enumerated type (e.g. List). There is no such concept in C#, you'll need to use a collection of some kind, or use the [Flags] attribute on your enumeration. – Mike Marshall Dec 15 '11 at 16:47
  • `[Flags] public enum DialogResult { None = 0, OK = 1, Cancel = 2, Abort = 4, Retry = 8, Ignore = 16, Yes = 32, No = 64 }` ? – chopikadze Dec 15 '11 at 16:47
  • Is there some reason you can't pass around a HashSet? – Erik Dietrich Dec 15 '11 at 16:47
  • 2
    Do you have some kind of problem with same sex marriages? – Jeff Dec 15 '11 at 16:52
  • 1
    @JeffN825 Bit the bullet and edited the questionable stuff out :-) – Adam Houldsworth Dec 15 '11 at 16:55
  • @JeffN825 Just because a state government dictates a policy, doesn't mean i have to agree with it. But the customer (a university) requires the software to have these checks. They can't just ignore the legal requirement, and i can't ignore a customer's requirement. Also M/F is a common enumeration situation - so i thought it would be helpful to have an enumeration everyone's dealt with. – Ian Boyd Dec 15 '11 at 17:00
  • @vc74 i thought about tagging the question; but in the past people have gotten grumpy when i do that – Ian Boyd Dec 15 '11 at 17:53
  • @JohnSaunders There might be nothing wrong with `HashSet`; i've never used `HashSet` before. i'll let you know after i try Adam's answer. – Ian Boyd Dec 15 '11 at 17:55
  • Honestly, I was just kidding around. – Jeff Dec 15 '11 at 18:24
  • @IanBoyd That's too bad, every now and then I miss Pascal's sets too and then in operator... – vc 74 Dec 16 '11 at 08:24
  • @JohnSaunders There is a problem with HashSet, you can't assign them (it copies references). – Ian Boyd Jan 05 '12 at 15:27
  • What do you mean you can't assign them, and what's the problem with copying references? – John Saunders Jan 05 '12 at 17:54

3 Answers3

6

Seems like you want an array of things. There are array types in C#, but nothing that is directly equivalent to your examples in terms of compiler support, closest is perhaps DialogResults[], an array of DialogResults.

Try supplying a HashSet of the items you allow. HashSet<T> implements ISet<T>, and it's usually best to work against interfaces than concrete types, especially for method signatures:

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

Then you can use Contains to test for items:

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

Somewhat pointless alternative: you could always implement your own Set<Enum> type using Jon Skeet's Unconstrained Melody to give you a nicer syntax from the perspective of the caller and get a little closer to your examples.

Adam Houldsworth
  • 63,413
  • 11
  • 150
  • 187
  • +1 but the method parameter should be of type `ISet` to permit the passing of other classes that implement `ISet`. – John Saunders Dec 15 '11 at 18:03
  • @JohnSaunders Didn't even realise there was an `ISet<>` interface, updated my answer to suit. – Adam Houldsworth Dec 15 '11 at 18:37
  • Hmm. i had an alias that defined the type (`public class PrizeEligibleTiers : HashSet {};`) What would be the `ISet<>` version of he `PrizeEligibleTiers` alias? – Ian Boyd Dec 15 '11 at 19:10
  • @IanBoyd: that's not an alias, that's a derived type. Since `HashSet` already implements `ISet`, you would not need to change that derived class. – John Saunders Dec 15 '11 at 19:39
  • @JohnSaunders But i would still like an alias so that i don't have to update source code when i change a type used globally (i.e. doesn't matter what PrizeEligibleTiers is, as long as it is) (Because i already have code that uses `PrizeEligibleTiers` and that type can keep that name, juts mean something else) – Ian Boyd Dec 15 '11 at 20:31
  • Ah, I see what you mean by "alias". An alternative I like is to use "var" instead of an explicit type name, whenever possible. It greatly helps reduce the amount of code that has to change whenever the type changes. – John Saunders Dec 15 '11 at 21:01
  • i was trying to figure out why `HashSet` didn't implement `ISet`. Then i realized that `HashSet` **doesn't** implement `ISet` (http://msdn.microsoft.com/en-us/library/bb359438(v=VS.90).aspx) – Ian Boyd Dec 16 '11 at 13:26
  • @IanBoyd 4.0 is your friend http://msdn.microsoft.com/en-us/library/bb359438(v=VS.100).aspx – Adam Houldsworth Dec 16 '11 at 13:27
  • @AdamHouldsworth Whoa whoa whoa, slow down there speedy. i'm hoping nobody will freak out that i bumped this project from 2.0 to 3.5SP1. – Ian Boyd Dec 16 '11 at 16:17
  • @IanBoyd It'll only be a headache for system admins if automatic updates for Windows are disabled :-) Simple answer, if you don't have the interface, just use `HashSet` directly. – Adam Houldsworth Dec 16 '11 at 16:21
2

I don't suppose you just mean using something like this?

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

with a .Select(dr => (DialogResult)dr).ToArray() if you want it strongly typed.

George Duckett
  • 31,770
  • 9
  • 95
  • 162
1

I think you want something like this:

foreach (var item in System.Enum.GetValues(typeof(PatronTier)))
{
    Console.WriteLine(item);
}
DaveShaw
  • 52,123
  • 16
  • 112
  • 141
iuristona
  • 927
  • 13
  • 30