[Flags]
public enum MyEnum
{
None = 0,
Setting1 = (1 << 1),
Setting2 = (1 << 2),
Setting3 = (1 << 3),
Setting4 = (1 << 4),
}
Run Code Online (Sandbox Code Playgroud)
我需要能够以某种方式循环每个可能的设置并将设置组合传递给函数.可悲的是,我一直无法弄清楚如何做到这一点
未经测试,使用风险自负,但应该足够一般地解决问题。System.Enum不是一个有效的限制,因为从技术上讲,C# 只允许在/与class后端的继承绕过这个 forEnum和ValueType。很抱歉丑陋的演员阵容。它也不是非常有效,但除非您针对动态生成的类型运行它,否则每次执行只需要执行一次(如果保存,则只需要执行一次)。
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;
}
Run Code Online (Sandbox Code Playgroud)
这是通过获取所有值并将它们组合在一起而不是求和来工作的,以防包含合数。然后它将每个整数取到最大值并用每个 Flag 的反向屏蔽它们,这导致有效位变为 0,允许我们识别那些不可能的位。
最后的检查是从枚举中丢失零。如果您可以在结果中始终包含零枚举,则可以将其删除。
当给出包含 2,4,6,32,34,16384 的枚举时,得到 15 的预期结果。
既然它是一个带标记的枚举,为什么不简单地:
一个例子看起来像这样
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());
}
Run Code Online (Sandbox Code Playgroud)