C# 如何不包含标志

C# 如何不包含标志,c#,enums,flags,enum-flags,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) {....} [标志] 公共枚举测试数 { A=1, B=2, C=4, D=8 } 公共静态IEnumerable AllNotContainin

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

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

public static IEnumerable<Enum> AllNotContaining(this Enum value)
{....}
[标志]
公共枚举测试数
{
A=1,
B=2,
C=4,
D=8
}
公共静态IEnumerable AllNotContaining(此枚举值)
{....}

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

步骤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,但对于标志枚举来说,这很奇怪(而且效率很低)。

请尝试这样做:

public static IEnumerable<TestEnum> AllNotContaining(this TestEnum value)
{
    return Enum.GetValues(typeof(TestEnum)).Cast<TestEnum>().Where(x => x != value).AsEnumerable();
}
public静态IEnumerable AllNotContaining(此TestEnum值)
{
返回Enum.GetValues(typeof(TestEnum)).Cast(),其中(x=>x!=value).AsEnumerable();
}

我还没有尝试润色下面的代码,但您应该了解一下大致思路:

  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;
      }
    }
  }
公共静态IEnumerable AllNotContaining(此T值)
//其中T:Enum(从C#7.3开始)。
{
//确定要检查的值的上限。
//例如,对于您的测试枚举,最大值为8,因此我们最多需要检查15。
var values=Enum.GetValues(typeof(T)).Cast();
int max=values.max()*2-1;
//测试所有值以查看给定标志是否存在。如果不存在,则返回它。

对于(inti=0;如果
value=TestEnum.A | TestEnum.C
您希望函数返回
{TestEnum.B,TestEnum.D}
?示例TestEnum.A.AllNotContaining()返回{2,4,8,6,10,12,14}将您的示例添加到问题中。此处的注释不算数。@panmigal请注意,标记的枚举的值应仅为2^x={1,2,4,8,16,32,…}。否则将导致错误。@ChrᴉZ:我想你会发现,当EnUM值不是两个幂时,标志属性不会造成任何错误。参见:<代码>!= 不足以标记一个枚举枚举-考虑<代码>(A C)。