[英]How do I check if more than one enum flag is set?
我只想知道是否设置了一个枚举标志,而不是哪个。 我目前的想法是检查它是否是 2 的幂。有没有更好的方法内置到枚举类型中?
[Flags]
enum Foo
{
Flag1 = 0x01,
Flag2 = 0x02,
Flag3 = 0x04,
Flag4 = 0x08,
Flag5 = 0x10,
Flag6 = 0x20,
Flag7 = 0x40,
Flag8 = 0x80
}
private bool ExactlynOneFlagSet(Foo myFoo)
{
var x = (byte) myFoo;
return (x != 0) && ((x & (x - 1)) == 0); //Check if a power of 2
}
if(!ExactlynOneFlagSet(Foo myFoo))
{
//Do something
}
它是一个位操作!
if ((myFoo & (myFoo -1)) != 0) //has more than 1 flag
该语句检查myFoo
的值是否不是 2 的幂。 或者,反之亦然,语句(myFoo & (myFoo -1)) == 0
检查二的幂。 这个想法是只有单个标志值是二的幂。 设置多个标志将导致myFoo
值的非二次myFoo
。
更多信息可以在这个对类似问题的回答中找到: https : //stackoverflow.com/a/1662162/2404788 。
有关位操作的更多信息,请访问http://en.wikipedia.org/wiki/Bitwise_operation
private bool ExatlyOneFlagSet(Foo myFoo)
{
return !myFoo.ToString().Contains(',');
}
如果枚举没有定义明确的标志组合,您可以检查枚举中是否定义了该值:
private bool ExactlynOneFlagSet(Foo myFoo)
{
return Enum.IsDefined(typeof(Foo), myFoo);
}
如果您使用 .NET Core 3.0+,则可以使用PopCount ,它返回uint
或ulong
中“1”位的数量并使用POPCNT
CPU 指令(如果 CPU 支持 SSE4,否则它将使用软件回退)。
public static bool ExactlyOneFlagSet(Foo foo)
{
return BitOperations.PopCount((ulong)foo) == 1;
}
Foo one = Foo.Flag1;
Foo two = Foo.Flag1 | Foo.Flag2;
Console.WriteLine(ExactlyOneFlagSet(one)); //true
Console.WriteLine(ExactlyOneFlagSet(two)); //false
正如雅各布在评论中解释的那样,您的方法根本不正确。 就我个人而言,我总是避免进行数学编程,尤其是在逻辑方面。 因此,我的解决方案类似于“如果我想知道计数为 1,则对其进行计数并将其与第一进行比较”。
这里是:
public static bool OneIsSet(Type enumType, byte value)
{
return Enum.GetValues(enumType).Cast<byte>().Count(v => (value & v) == v) == 1;
}
public static bool OneIsSet(Type enumType, int value)
{
return Enum.GetValues(enumType).Cast<byte>().Count(v => (value & v) == v) == 1;
}
你可以像这样将它用于你的 foo 类型:
var toReturnFalse = (byte)(foo.Flag1 | foo.Flag2);
var toReturnTrue = (byte)foo.Flag1;
var trueWillBeReturned = OneIsSet(typeof(foo), toReturnTrue);
var falseWillBeReturned = OneIsSet(typeof(foo), toReturnFalse);
我相信可以使用泛型和类型处理方法以更通用的方式编写这些方法。 但是,我包括了最常见的枚举基本类型的方法,这些方法是 int 和 byte。 但是您也可以为 short 和其他类型编写相同的代码。 您也可以在代码中内联代码。 它只有一行代码。
同样使用此方法,您可以查看设置标志的数量是否为两个或更多。 如果设置标志的计数等于“n”,则以下代码返回 true。
Enum.GetValues(enumType).Cast<byte>().Count(v => (value & v) == v) == n;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.