Using C# Enum Flags To Return A Set Of Values Based On Their Bit-Wise OR'ed Values

1.6k Views Asked by At

I understand that you can configure C# enum flags in this way:

    [Flags]
    public enum MyEnum
    {
        Unknown = 0,
        Type1 = 1,
        Type2 = 2,
        Type3 = 4,
        Type4 = 8,
        Type5 = 16
    }

And once this is configured, you can represent a set of enumberations like so:

MyEnum enumerationSet = MyEnum.Type1 | MyEnum.Type2

Then you can make checks against this set, such as:

if(enumerationSet.HasFlag(MyEnum.Type1))
{
  // Do something
}

Or print their values, like so:

Console.WriteLine("{0}", enumerationSet);

Which would print:

Type1, Type2

However, can I go in reverse order? For instance, if I know that

MyEnum.Type1 | MyEnum.Type2 == 3

Can I then ask MyEnum what set of its value/types would equal 3? Then, I can create an extension method (GetSet) to execute like this:

List<MyEnum> myEnumSetList = MyEnum.GetSet(3)

Returning either a MyEnum set or a set of values, i.e. {1, 2}.

Please advise.


EDIT: I was able to finally figure it out. Posted my answer below.

4

There are 4 best solutions below

0
On BEST ANSWER

After some hacking around, I was able to resolve a list of enum values, based on the value of that respective set OR'ed:

protected List<MyEnum> GetEnumSet(int flagNumber)
{
      List<MyEnum> resultList= new List<MyEnum>();

      foreach (MyEnum value in Enum.GetValues(typeof(MyEnum)))
      {
         if (((MyEnum)flagNumber).HasFlag(value))
         {
             resultList.Add(value);
         }
      }

      return resultList;
}

Here, flagNumber is the value of a respective list OR'ed, i.e. MyEnum.Type1 | MyEnum.Type2. Thus, by sending this method the flagNumber, I get the list { MyEnum.Type1, MyEnum.Type2 }

0
On

You can just cast the Integer to an Enum and use an & comparison.

example

var num = 1;
var doesExist = (((enumerationSet) & ((MyEnum) num)) != 0);

Then if it exists you can return it in your extension method.

Full Code

 var enumList = new List<MyEnum>();
            var testNumbers = new List<int>{ 1, 2, 4};
            MyEnum enumerationSet = MyEnum.Type1 | MyEnum.Type2;
            foreach (var num in testNumbers)
            {
                var doesExist = (((enumerationSet) & ((MyEnum) num)) != 0);
                if (doesExist)
                    enumList.Add((MyEnum)num);
            }

            enumList.ForEach(x => Console.WriteLine(x.ToString()));
            return enumList;
0
On

You can parse it manually with this code:

    var res = 3;
    var myEnumSetList = res.ToString()
              .Split(new[] { ", " }, StringSplitOptions.None)
              .Select(v => (MyEnum)Enum.Parse(typeof(MyEnum), v)).ToList();
0
On

If you want a list of flags you can use this:

var f = 1 + 4 + 8;
var s = Convert.ToString(f, 2);
var flags =
    s.Where(w=> w !='0').Select(
        (c, i) =>
            (MyEnum)Enum.Parse(typeof(MyEnum),
                    (int.Parse(c.ToString())*Math.Pow(2, i)).ToString(CultureInfo.InvariantCulture)));