如何不包含标志

时间:2018-09-20 07:48:12

标签: c# enums flags enum-flags

我有枚举标志。如何获得不包含特定标志的所有标志组合?

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

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

例如,TestEnum.A.AllNotContaining()应该返回{2, 4, 6, 8, 10, 12, 14}

3 个答案:

答案 0 :(得分:3)

步骤1,使用二进制NOT:

var notUsedBits = ~ value;

但这将设置所有未使用的32位。

所以您可能需要口罩:

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

然后方法变为

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

这不会返回IEnumerable,但对于Flags枚举来说还是很奇怪的(而且效率低下)。

答案 1 :(得分:1)

我还没有尝试完善下面的代码,但是您应该了解一下总体思路:

  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;
      }
    }
  }

答案 2 :(得分:0)

尝试这样:

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