Combine multiple enums into master enum list
Asked Answered
S

4

25

Is it possible to combine multiple enums together? Below is code sample of what I would like to see:

enum PrimaryColors
{
   Red,
   Yellow,
   Blue
}

enum SecondaryColors
{
   Orange,
   Green,
   Purple
}

//Combine them into a new enum somehow to result in:
enum AllColors
{
   Red,
   Orange,
   Yellow,
   Green,
   Blue,
   Purple
}

It does not matter what order they are, or what their backing numbers are, I just want to be able to combine them.

For context, this is so that multiple classes for a program I am working on would have enums associated with what they do. My main program would read all of the enums available from each of the support classes and make a master list of available enums of available commands (the the enums are for).

Edit: The reason for these enums is because my main program is reading in a list of commands to perform at certain times, and so I want to read in the file, see if the command in it is associated with one of my enums, and if it is, put it into a list of commands to perform.

Southwest answered 5/12, 2012 at 23:56 Comment(10)
enum is fundamentally a compile-time concept. Are you looking to produce a C# file that contains a definition of something similar to AllColors, or are you trying to do something else?Anderson
Are you trying to create the combined type AllColors programmatically, I mean, not create it until your application is running? If you just want to add them into a list, remember that all enums have System.Object and System.Enum as their base classes. You could create some list based on one of those classes. Your enum values would be boxed, of course, but that's probably not a problem.Syllogism
Why limit yourself to enums?Clastic
@dasblinkenlight I am basically making a program that handles different things via support files. So if a "legs" enum had values of "walk" and "dance", and an arms enum had values of "grasp" and "wave", then I want the limbs enum to know that the possible actions are "walk", "dance", "grasp", and "wave". I am trying to keep enums associated with certain support files in those support files to decrease coupling between the main program and its support files.Southwest
Why don't you simply use lists of strings where each string represents a command?Haas
I added a little more context above. Also, it would be okay if they were boxed to some extent like Allcolors.PrimaryColors.Red.Southwest
What are you going to do about same enums? For instance, "fingers" and "toes" can both "grasp" and "wiggle". But that might be all the shared functionality--- for instance, "fingers" can "gesture" and "sign" while toes cannot.Wame
@Haas I am seriously considering your suggestion about using a list of strings. They are far easier to work with in this situation, and I'm using a switch to determine which string is associated with it anyway.Southwest
@Wame In this case, I would make the rule of unique names only, since I am reading in a list of commands to perform, they have to be unique there. So I would have something like fingersGrasp, fingersWiggle, toesGrasp, etc.Southwest
Similar to TypeScript: enum eX = eA & eB. It would be nice to combine two existing enumerations in .NET to adhere to the DRY concept.Sedan
S
10

Not sure I understand precisely. But you can make a List<> of all the values like this:

var allColors = new List<Enum>();

allColors.AddRange(Enum.GetValues(typeof(PrimaryColors)).Cast<Enum>());
allColors.AddRange(Enum.GetValues(typeof(SecondaryColors)).Cast<Enum>());

Instead of List<Enum> you could also use HashSet<Enum>. In any case, because you assign a PrimaryColor or SecondaryColor to a class type (namely System.Enum), you get boxing, but that's just a technical detail (probably).

Syllogism answered 6/12, 2012 at 0:16 Comment(3)
BTW, HashSet most likely doesn't make sense here as a performance optimization. But it could make sense if you're using it to make the intent more clear.Lowboy
This code does not appear to work when I tried it. In a sample program based on this, I got the errors: The best overloaded method match for 'System.Collections.Generic.List<System.Enum>.AddRange(System.Collections.Generic.IEnumerable<System.Enum>)' has some invalid arguments and Argument 1: cannot convert from 'System.Collections.Generic.IEnumerable<ConsoleApplication1.Program.PrimaryColors>' to 'System.Collections.Generic.IEnumerable<System.Enum>'Southwest
@Lowboy Agree. By the way, there's a great risk that the hash codes of the different types collide, for example Red collides with Orange, and so on. So it's not for the performance of it. The instance method Equals(object) does however work fine (it is overridden by enums to check the type of the argument, and then check if the underlying integer value agrees).Syllogism
L
7

The reason for these enums is because my main program is reading in a list of commands to perform at certain times, and so I want to read in the file, see if the command in it is associated with one of my enums, and if it is, put it into a list of commands to perform.

This seems like you don't want three different enum types, you want one type (what you call “master enum”) plus some way to decide which of the sub-enums a certain value belongs to. To do that, you can use a collection of values from your master enum, or a switch.

For example:

enum Color
{
   Red,
   Orange,
   Yellow,
   Green,
   Blue,
   Purple
}

bool IsPrimaryColor(Color color)
{
    switch (color)
    {
    case Color.Red:
    case Color.Yellow:
    case Color.Blue:
        return true;
    default:
        return false;
    }
}

Also, you should use a singular name for enum types (unless it's a flag enum).

Lowboy answered 6/12, 2012 at 0:14 Comment(0)
M
4

You can derive the sub-groups from the complete group.
An example:

enum AllColors 
{
   Red,
   Orange,
   Yellow,
   Green,
   Blue,
   Purple
}

enum PrimaryColors
{
   Red = AllColors.Red,
   Yellow = AllColors.Yellow,
   Blue = AllColors.Blue
}

enum SecondaryColors
{
   Orange = AllColors.Orange,
   Green = AllColors.Green,
   Purple = AllColors.Purple
}
Maitilde answered 24/3, 2021 at 3:22 Comment(1)
This works, but be careful if you're going in the reverse, i.e. deriving the group from the subgroups; unless you assign non-overlapping int values to the subgroup items, you will get overlapping items in the complete group. Not technically illegal, but a potential problem if you're not expecting it. Fiddle example.Dissonant
D
3

Keep it simple and just use the implicit int conversions, or use the System.Enum.Parse() function:

enum PrimaryColors
{        
    Red = 0,
    Yellow = 2,
    Blue = 4
}

enum SecondaryColors
{
    Orange = 1,
    Green = 3,
    Purple = 5
}

//Combine them into a new enum somehow to result in:
enum AllColors
{
    Red = 0,
    Orange,
    Yellow,
    Green,
    Blue,
    Purple
}

class Program
{
    static AllColors ParseColor(Enum color)
    {
        return ParseColor(color.ToString());
    }
    static AllColors ParseColor(string color)
    {
        return (AllColors)Enum.Parse(typeof(AllColors), color);
    }
    static void Main(string[] args)
    {
        PrimaryColors color1=PrimaryColors.Red;
        AllColors result=(AllColors)color1;
        // AllColors.Red

        SecondaryColors color2=SecondaryColors.Green;
        AllColors other=(AllColors)color2; 
        // AllColors.Green

        AllColors final=ParseColor(PrimaryColors.Yellow);
        // AllColors.Yellow
    }
}
Dishman answered 6/12, 2012 at 0:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.