Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/280.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何获取枚举(标志)的所有可能组合 [标志] 公共枚举髓鞘 { 无=0, Setting1=(1_C#_Enum Flags - Fatal编程技术网

C# 如何获取枚举(标志)的所有可能组合 [标志] 公共枚举髓鞘 { 无=0, Setting1=(1

C# 如何获取枚举(标志)的所有可能组合 [标志] 公共枚举髓鞘 { 无=0, Setting1=(1,c#,enum-flags,C#,Enum Flags,这里是一个针对您的代码示例的解决方案,使用一个简单的for循环(不要使用,请参阅下面的更新) int max=(int)(MyEnum.Setting1 | MyEnum.Setting2 | MyEnum.Setting3 | MyEnum.Setting4); 对于(int i=0;i 0) { T a=queue.Dequeue(); foreach(初始值中的tb) { T combo=orFunction(a,b); 如果(发现组合。添加(组合)) 队列。排队(组合); } } 返回发

这里是一个针对您的代码示例的解决方案,使用一个简单的for循环(不要使用,请参阅下面的更新)

int max=(int)(MyEnum.Setting1 | MyEnum.Setting2 | MyEnum.Setting3 | MyEnum.Setting4);
对于(int i=0;i 0)
{
T a=queue.Dequeue();
foreach(初始值中的tb)
{
T combo=orFunction(a,b);
如果(发现组合。添加(组合))
队列。排队(组合);
}
}
返回发现的组合;
}

首先,获取所有单个值的列表。由于您有5个值,这就是
(1在向枚举添加新成员时,我通常不想更新表示枚举最大值的每个变量。
例如,我不喜欢格雷格提出的声明:

List<MyEnum> allValues = new List<MyEnum>(Enum.Getvalues(typeof(MyEnum)));
HashSet<MyEnum> allCombos = new Hashset<MyEnum>();

for(int i = 1; i < (1<<allValues.Count); i++)
{
    MyEnum working = (MyEnum)0;
    int index = 0;
    int checker = i;
    while(checker != 0)
    {
        if(checker & 0x01 == 0x01) working |= allValues[index];
        checker = checker >> 1;
        index++;
    }
    allCombos.Add(working);
}
考虑一下,当您的解决方案中分散了几个变量,并且您决定修改枚举时,这肯定不是一个理想的情况

我会事先承认我的代码比较慢,但在修改枚举后它会自动正确,我会努力以一种健壮的方式编写代码。我愿意为此付出一些计算代价,C#就是这样。我建议:

int max = (int)(MyEnum.Setting1 | MyEnum.Setting2 | ... | MyEnum.SettingN);
public静态IEnumerable GetAllValues(),其中T:struct
{
如果(!typeof(T).IsEnum)抛出新的ArgumentException(“泛型参数不是枚举类型”);

int maxEnumValue=(1未经测试,使用风险自负,但应足够普遍地解决问题。
System.Enum
不是一个有效的限制,因为从技术上讲,C#只允许在
class
中/与
一起继承。后端对
Enum
ValueType
绕过此限制。对于难看的转换,非常抱歉。它的效率也不高但是,除非您针对动态生成的类型运行此操作,否则每次执行只需执行一次(如果保存,则只需执行一次)

公共静态列表GetAllEnums()
其中T:struct
//使用C#7.3,其中T:Enum起作用
{
//如果添加T:Enum,则不需要
if(typeof(T).BaseType!=typeof(Enum))抛出新的ArgumentException(“T必须是枚举类型”);
//Enum.GetValues的返回类型是Array,但实际上是int[]per docs
//此位转换为int[]
var values=Enum.GetValues(typeof(T)).Cast().ToArray();
if(!typeof(T).GetCustomAttributes(typeof(FlagsAttribute),false).Any())
{
//我们没有标志,所以只返回GetValues的结果
返回值;
}
var valuesInverted=values.Select(v=>~v.ToArray();
int max=0;
for(int i=0;ipublic IEnumerable AllCombinations(),其中TEnum:struct
{
类型enumType=typeof(TEnum);
如果(!enumType.IsEnum)
抛出新的ArgumentException(string.Format(“类型{0}不表示枚举。”,enumType),“TEnum”);
if(enumType.GetCustomAttributes(typeof(FlagsAttribute),true).Length>0)//具有Flags属性
{
var allcombines=new HashSet();
var underyingtype=Enum.getunderyingtype(enumType);
if(underyingtype==typeof(sbyte)| | underyingtype==typeof(short)| | underyingtype==typeof(int)| | underyingtype==typeof(long))
{
long[]enumValues=Array.ConvertAll((TEnum[])Enum.GetValues(enumType),value=>Convert.ToInt64(value));
for(int i=0;iConvert.ToUInt64(value));
for(int i=0;i
既然它是一个带标记的枚举,为什么不简单地:

  • 获取枚举的最高值
  • 计算组合的数量,即上限
  • 迭代每个组合,即从0循环到上限
  • 下面是一个例子

        public IEnumerable<TEnum> AllCombinations<TEnum>() where TEnum : struct
        {
            Type enumType = typeof (TEnum);
            if (!enumType.IsEnum)
                throw new ArgumentException(string.Format("The type {0} does not represent an enumeration.", enumType), "TEnum");
    
            if (enumType.GetCustomAttributes(typeof (FlagsAttribute), true).Length > 0) //Has Flags attribute
            {
                var allCombinations = new HashSet<TEnum>();
    
                var underlyingType = Enum.GetUnderlyingType(enumType);
                if (underlyingType == typeof (sbyte) || underlyingType == typeof (short) || underlyingType == typeof (int) || underlyingType == typeof (long))
                {
                    long[] enumValues = Array.ConvertAll((TEnum[]) Enum.GetValues(enumType), value => Convert.ToInt64(value));
                    for (int i = 0; i < enumValues.Length; i++)
                        FillCombinationsRecursive(enumValues[i], i + 1, enumValues, allCombinations);
                }
                else if (underlyingType == typeof (byte) || underlyingType == typeof (ushort) || underlyingType == typeof (uint) || underlyingType == typeof (ulong))
                {
                    ulong[] enumValues = Array.ConvertAll((TEnum[]) Enum.GetValues(enumType), value => Convert.ToUInt64(value));
                    for (int i = 0; i < enumValues.Length; i++)
                        FillCombinationsRecursive(enumValues[i], i + 1, enumValues, allCombinations);
                }
                return allCombinations;
            }
            //No Flags attribute
            return (TEnum[]) Enum.GetValues(enumType);
        }
    
        private void FillCombinationsRecursive<TEnum>(long combination, int start, long[] initialValues, HashSet<TEnum> combinations) where TEnum : struct
        {
            combinations.Add((TEnum)Enum.ToObject(typeof(TEnum), combination));
            if (combination == 0)
                return;
    
            for (int i = start; i < initialValues.Length; i++)
            {
                var nextCombination = combination | initialValues[i];
                FillCombinationsRecursive(nextCombination, i + 1, initialValues, combinations);
            }
        }
    
        private void FillCombinationsRecursive<TEnum>(ulong combination, int start, ulong[] initialValues, HashSet<TEnum> combinations) where TEnum : struct
        {
            combinations.Add((TEnum)Enum.ToObject(typeof(TEnum), combination));
            if (combination == 0)
                return;
    
            for (int i = start; i < initialValues.Length; i++)
            {
                var nextCombination = combination | initialValues[i];
                FillCombinationsRecursive(nextCombination, i + 1, initialValues, combinations);
            }
        }
    
    var highestEnum=Enum.GetValues(typeof(MyEnum)).Cast().Max();
    var上限=最高数*2;
    for(int i=0;i
    我参加我想参加的聚会可能有点晚了
    List<MyEnum> allValues = new List<MyEnum>(Enum.Getvalues(typeof(MyEnum)));
    HashSet<MyEnum> allCombos = new Hashset<MyEnum>();
    
    for(int i = 1; i < (1<<allValues.Count); i++)
    {
        MyEnum working = (MyEnum)0;
        int index = 0;
        int checker = i;
        while(checker != 0)
        {
            if(checker & 0x01 == 0x01) working |= allValues[index];
            checker = checker >> 1;
            index++;
        }
        allCombos.Add(working);
    }
    
    int max = (int)(MyEnum.Setting1 | MyEnum.Setting2 | ... | MyEnum.SettingN);
    
    public static IEnumerable<T> GetAllValues<T>() where T : struct
    {
        if (!typeof(T).IsEnum) throw new ArgumentException("Generic argument is not an enumeration type");
        int maxEnumValue = (1 << Enum.GetValues(typeof(T)).Length) - 1;
        return Enumerable.Range(0, maxEnumValue).Cast<T>();
    }
    
    public static List<T> GetAllEnums<T>()
        where T : struct
        // With C# 7.3 where T : Enum works
    {
        // Unneeded if you add T : Enum
        if (typeof(T).BaseType != typeof(Enum)) throw new ArgumentException("T must be an Enum type");
    
        // The return type of Enum.GetValues is Array but it is effectively int[] per docs
        // This bit converts to int[]
        var values = Enum.GetValues(typeof(T)).Cast<int>().ToArray();
    
        if (!typeof(T).GetCustomAttributes(typeof(FlagsAttribute), false).Any())
        {
            // We don't have flags so just return the result of GetValues
            return values;
        }
    
        var valuesInverted = values.Select(v => ~v).ToArray();
        int max = 0;
        for (int i = 0; i < values.Length; i++)
        {
            max |= values[i];
        }
    
        var result = new List<T>();
        for (int i = 0; i <= max; i++)
        {
            int unaccountedBits = i;
            for (int j = 0; j < valuesInverted.Length; j++)
            {
                // This step removes each flag that is set in one of the Enums thus ensuring that an Enum with missing bits won't be passed an int that has those bits set
                unaccountedBits &= valuesInverted[j];
                if (unaccountedBits == 0)
                {
                    result.Add((T)(object)i);
                    break;
                }
            }
        }
    
        //Check for zero
        try
        {
            if (string.IsNullOrEmpty(Enum.GetName(typeof(T), (T)(object)0)))
            {
                result.Remove((T)(object)0);
            }
        }
        catch
        {
            result.Remove((T)(object)0);
        }
    
        return result;
    }
    
        public IEnumerable<TEnum> AllCombinations<TEnum>() where TEnum : struct
        {
            Type enumType = typeof (TEnum);
            if (!enumType.IsEnum)
                throw new ArgumentException(string.Format("The type {0} does not represent an enumeration.", enumType), "TEnum");
    
            if (enumType.GetCustomAttributes(typeof (FlagsAttribute), true).Length > 0) //Has Flags attribute
            {
                var allCombinations = new HashSet<TEnum>();
    
                var underlyingType = Enum.GetUnderlyingType(enumType);
                if (underlyingType == typeof (sbyte) || underlyingType == typeof (short) || underlyingType == typeof (int) || underlyingType == typeof (long))
                {
                    long[] enumValues = Array.ConvertAll((TEnum[]) Enum.GetValues(enumType), value => Convert.ToInt64(value));
                    for (int i = 0; i < enumValues.Length; i++)
                        FillCombinationsRecursive(enumValues[i], i + 1, enumValues, allCombinations);
                }
                else if (underlyingType == typeof (byte) || underlyingType == typeof (ushort) || underlyingType == typeof (uint) || underlyingType == typeof (ulong))
                {
                    ulong[] enumValues = Array.ConvertAll((TEnum[]) Enum.GetValues(enumType), value => Convert.ToUInt64(value));
                    for (int i = 0; i < enumValues.Length; i++)
                        FillCombinationsRecursive(enumValues[i], i + 1, enumValues, allCombinations);
                }
                return allCombinations;
            }
            //No Flags attribute
            return (TEnum[]) Enum.GetValues(enumType);
        }
    
        private void FillCombinationsRecursive<TEnum>(long combination, int start, long[] initialValues, HashSet<TEnum> combinations) where TEnum : struct
        {
            combinations.Add((TEnum)Enum.ToObject(typeof(TEnum), combination));
            if (combination == 0)
                return;
    
            for (int i = start; i < initialValues.Length; i++)
            {
                var nextCombination = combination | initialValues[i];
                FillCombinationsRecursive(nextCombination, i + 1, initialValues, combinations);
            }
        }
    
        private void FillCombinationsRecursive<TEnum>(ulong combination, int start, ulong[] initialValues, HashSet<TEnum> combinations) where TEnum : struct
        {
            combinations.Add((TEnum)Enum.ToObject(typeof(TEnum), combination));
            if (combination == 0)
                return;
    
            for (int i = start; i < initialValues.Length; i++)
            {
                var nextCombination = combination | initialValues[i];
                FillCombinationsRecursive(nextCombination, i + 1, initialValues, combinations);
            }
        }
    
    var highestEnum = Enum.GetValues(typeof(MyEnum)).Cast<int>().Max();
    var upperBound = highestEnum * 2;    
    for (int i = 0; i < upperBound; i++)
    {
        Console.WriteLine(((MyEnum)i).ToString());
    }
    
    public static Dictionary<int,string> GetCombinations( this Enum enu)
        {
            var fields = enu.GetType()
                            .GetFields()
                            .Where(f => f.Name != "value__")
                            .DistinctBy(f=> Convert.ToInt32(f.GetRawConstantValue()));
    
            var result = fields.ToDictionary(f=>Convert.ToInt32(f.GetRawConstantValue()), f => f.Name);
    
            int max = Enum.GetValues(enu.GetType()).Cast<int>().Max();
            int upperBound = max * 2;
    
            for (int i = 0 ; i <= upperBound ; i += 2)
            {
                string s = Convert.ToString(i, 2).PadLeft(Math.Abs(i-max),'0');
                Boolean[] bits = s.Select(chs => chs == '1' ? true : false)
                                 .Reverse()
                                 .ToArray();
    
                if (!result.ContainsKey(i))
                {
                    var newComb = string.Empty;
                    for (int j = 1; j < bits.Count(); j++)
                    {
                        var idx = 1 << j;
                        if (bits[j] && result.ContainsKey(idx))
                        {
                            newComb = newComb + result[idx] + " | ";
                        }
                    }                                      
                    newComb = newComb.Trim(new char[] { ' ', '|' });
                    if (!result.ContainsValue(newComb) && !string.IsNullOrEmpty(newComb))
                    {
                        result.Add(i, newComb);
                    }                    
                }
            }
            return result;
        }
    
    public IEnumerable<T> AllCombinations<T>() where T : struct
    {
        var type = typeof(T);
        for (var combination = 0; combination < Enum.GetValues(type).Cast<int>().Max()*2; combination++)
        {
            yield return (T)Enum.ToObject(type, combination);
        }
    }
    
    public IEnumerable<T> AllCombinations<T>() where T : struct
    {
        var type = typeof(T);
        if (!type.IsEnum)
        {
            throw new ArgumentException($"Type parameter '{nameof(T)}' must be an Enum type.");
        }
    
        for (var combination = 0; combination < Enum.GetValues(type).Cast<int>().Max()*2; combination++)
        {
            var result = (T)Enum.ToObject(type, combination);
    
            // Optional check for legal combination.
            // (and is not necessary if all flag a ascending exponent of 2 like 2, 4, 8...
            if (result.ToString() == combination.ToString() && combination != 0)
            {
                continue;
            }
    
            yield return result;
        }
    }