panmigal
panmigal

Reputation: 111

How get not containing flags

I have enum flags. How to get all combinations of flags that do not contain a specific one?

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

public static IEnumerable<Enum> AllNotContaining(this Enum value)
{....}

For example, TestEnum.A.AllNotContaining() should return {2, 4, 6, 8, 10, 12, 14}.

Upvotes: 2

Views: 990

Answers (3)

CompuChip
CompuChip

Reputation: 9232

I haven't tried to polish the code below, but you should get the general idea:

  public static IEnumerable<int> AllNotContaining<T>(this T value)
    // where T : Enum  (as of C# 7.3).
  {
    // Determine upper bound of values to check.
    // E.g. for your test enum, the maximum value is 8 so we need to check up to 15.
    var values = Enum.GetValues(typeof(T)).Cast<int>();
    int max = values.Max() * 2 - 1;

    // Test all values to see if the given flag is present. If not, return it.
    for(int i = 0; i <= max; ++i)
    {
      // Possibly also: if( ((Enum)i).HasFlags(value))
      if((max & Convert.ToInt32(value)) == 0)
      {
        yield return i;
      }
    }
  }

Upvotes: 1

Hossein
Hossein

Reputation: 3113

Try like this:

public static IEnumerable<TestEnum> AllNotContaining(this TestEnum value)
{
    return Enum.GetValues(typeof(TestEnum)).Cast<TestEnum>().Where(x => x != value).AsEnumerable();
}

Upvotes: 0

Henk Holterman
Henk Holterman

Reputation: 273774

Step 1, use the binary NOT:

var notUsedBits = ~ value;

But this will set all of the 32 bits that were not used.

So you will probably want a mask:

[Flags]
public enum TestEnum
{
    A = 1,
    B = 2,
    C = 4,
    D = 8,    
    All = A|B|C|D,  // or compute this inside the method    
}

and then the method becomes

// untested
public static TestEnum AllNotContaining(this TestEnum value)
{
    return ~ value & TestEnum.All;
}

this does not return an IEnumerable but that is weird (and inefficient) for a Flags enum anyway.

Upvotes: 4

Related Questions