C# Flags - 获取可以存在给定标志的所有可能组合

C# Flags - Getting all possible combinations where a given flag can be present

考虑以下枚举:

Enum AnimalType
{
  Dog = 1,
  Cat = 2,
  Bird = 4,
  Wolf = 8
} 

现在假设我们想要找到所有可能的标志组合,例如 Dog 处于活动状态。

我分为以下方法来做到这一点:

public static int[] testss(int value)
    {
        var animalTypes = (AnimalType)value;
        List<int> possibleValues = new List<int>();
        possibleValues.Add(value);

        int totalEnumValues = Enum.GetNames(typeof(AnimalType)).Length;
        List<int> helper = new List<int>();
        int cnt = 0;

        for (int i = 1; i < totalEnumValues; i++)
        {
            foreach (Enum val in Enum.GetValues(animalTypes.GetType()))
            {
                if (cnt >= i)
                    break;

                if (i == 1)
                {
                    if ((AnimalType)val != (AnimalType)value)
                    {
                        possibleValues.Add((int)(AnimalType)val + value);
                    }
                }
                else
                {                        
                    if ((AnimalType)val != (AnimalType)value && (cnt < i))
                    {
                        helper.Add((int)(AnimalType)val);
                        cnt += 1;
                    }                        
                }
            }

            if (cnt > 0)
            {
                possibleValues.Add(helper.Sum() + value);

                helper = new List<int>();
                cnt = 0;
            }
        }         

        return possibleValues.ToArray();
    }

此方法将构建一个数组,其中包含所有可能的数字表示形式,其中包含作为输入的给定标志。

它仅部分起作用,例如,如果您针对 Dog (1) 对其进行测试,您会发现 possibleValues 数组中缺少 2 个值。

你能帮我看看哪里做错了吗?

您可以使用 [Flags] 枚举属性,然后是扩展方法。像这样:

[Flags]
enum AnimalType
{
  Dog = 1,
  Cat = 2,
  Bird = 4,
  Wolf = 8
} 

static class Program
{
    static void Main(string[] args)
    {
        var test = AnimalType.Dog.AllContaining();
    }

    public static int[] AllContaining(this AnimalType thisAnimal)
    {
        List<int> retVal = new List<int>();
        var possibleEnums = Enum.GetValues(typeof(AnimalType)).Length;
        var maxValue = (int)Math.Pow(2, possibleEnums);

        for (int i = 0; i < maxValue; i++)
        {
            if (((AnimalType)i).HasFlag(thisAnimal))
            {
                retVal.Add(i);
            }
        }
        return retVal.ToArray();
    }
}

它遍历枚举的所有可能的整数值,并查看所提供动物的 'flag' 是否存在。如果是,它会添加到 return 数组。

假设枚举值不多,你可以试试:

        private static void Main(string[] args)
        {
            var type = AnimalType.Wolf;

            foreach (var x in GetAllPossibleCombinationWith(type))
            {
                Console.WriteLine(x);
            }


            Console.ReadLine();
        }


        public static IEnumerable<AnimalType> GetAllPossibleCombinationWith(AnimalType type) // Bird
        {
            var maxValue = Enum.GetValues(typeof(AnimalType)).Cast<int>().Max();
            var combinationValue =2* maxValue - 1;
            for (int i = 0; i < combinationValue; i++)
            {
                var val = (AnimalType) i;
                if ((val & type) == type) yield return val;
            }
        }

        [Flags]
        public enum AnimalType
        {
            Dog = 1,
            Cat = 2,
            Bird = 4,
            Wolf = 8,
            Fish = 16
        }

它假定标志值中没有 "hole"。