简体   繁体   中英

Union of enum members in C#

Let us say, I have an enum BasicType , which is defined as follows:

    public enum ObjectType{
        A = 1,
        B = 2,
        C = 3,
    }

The BasicType identifies performs a ternary classification of any Object . Subsequently, I realized that the objects A and B need to be treated in a similar way as compared to C , so I defined another enum ObjectGroupType as follows :

public enum ObjectGroupType
{
   AB = 1,
   C = 2,
}

With the new enum, I am able to bucket objects of several known types as one. So, when I receive a stream of objects in various types, I actually identify whether they belong to AB or C type. Is there an elegant workaround for this? For instance, will I be able to assign the same enum values for A and B in the ObjectGroupType ?:

Edit 1 : I am unable to find the resemblance to the question here

Edit 2 : Thank you Maurice for your constructive inputs -- taking cues from your answer, I came up with this redefined ObjectGroupType .

 public enum ObjectGroupType
 {
    AB = ObjectType.A | ObjectType.B
    C = 2,
 }

Is this valid?

Essentially, when I process a stream of objects of type AB, I want to ascertain Type A or Type B objects. This is quite similar to a hierarchical two-level decision tree:

    object
    /     \
 AB        C
 /\
A  B

I apologize in advance if I misread your intent, but it almost sounds like you want to allow multiple different enum types to be acted on in your code based on the enum value. The good thing is that you can do that already with bitwise operations and enums.

Given an enum that looks like this:

[Flags]
enum ObjectType
{
    A = 1,
    B = 2,
    C = 4,
    D = 8
}

You can set a comparison value that is the bitwise OR of several values:

var allowedValues = ObjectType.A | ObjectType.C;

This works because the values in the enum act like bit fields under the covers.

When you run your code, you do a bitwise AND on the allowedValues variable and the test variable and see if it matches your test variable. If it does, then it is one of the values you want:

if ((test & allowed) == test) ...

Below is a working example using the enum above that shows you how it works.

void Main()
{
    var allowed = ObjectType.A | ObjectType.C;

    var values = new int [] { 1, 2, 4, 8 };

    foreach (var i in values)
    {
        var test = (ObjectType)i;

        if ((test & allowed) == test)
        {
            Console.WriteLine("Found a match: {0}", test);
        }
        else
        {
            Console.WriteLine("No match: {0}", test);
        }
    }
}

Best of luck!

You might use a int instead of an enum, use values that don't overlap when combined (ie values whose binary representation has only one bit on) and then perform a mask operation on the ObjectType of a parameter to determine if it is AB:

class SomeClass
{
    public static class ObjectType
    {
        public const int A = 1;
        public const int B = 2;
        public const int C = 4;
        public const int D = 8;
    }

    public int MyType;
    public string Title;
    static void Main(string[] args)
    {
        List<SomeClass> list = new List<SomeClass>()
        {
            new SomeClass() {Title ="I am of type A", MyType = ObjectType.A }
            ,new SomeClass() {Title ="I am of type B", MyType = ObjectType.B }
            ,new SomeClass() {Title ="I am of type AB", MyType = ObjectType.A | ObjectType.B }
        };

        list.ForEach(p => { if (p.MyType == (ObjectType.A | ObjectType.B)) Console.WriteLine(p.Title); });
    }
}

The downside of this approach is losing strong-typing of Object Type, ie you can assign any value not just those you define in the ObjectType.

Edit:

I found the answer of Maurice Reeves very good, I only want to bring some more info:

   [Flags]
    public enum ObjectType
{
    None=0,
    A = 1,
    B = 2,
    C = 4,
    D = 8,
    E = 16,
    AorB=A|B,
    BorCorD=B|C|D,

}

By using [Flags] attribute, you can create sets of enum items, which can help you establishing different business rules for each set.

In order to check if and item exist in a set you can do as follow:

public static bool IsAorB(this ObjectType item)
{
      return ObjectType.AorB.HasFlag(item);
}

if you want to creat on the fly new set of items, you can do:

var newGroup=ObjectType.A | ObjectType.BorCorD;

if you want to apply some business rule to a set, except an item, you can do:

var newGroupExceptC =newGroup^=ObjectType.C;

Now if you check if element C exist in the set you will get false:

bool exist=newGroupExceptC.HasFlag(ObjectType.C) // =false

more info you can find here

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM