简体   繁体   English

如何检查是否设置了多个枚举标志?

[英]How do I check if more than one enum flag is set?

I just want to know if exactly one enum flag is set, not which ones.我只想知道是否设置了一个枚举标志,而不是哪个。 My current thinking is to check if it is a power of 2. Is there a better way built into enum types?我目前的想法是检查它是否是 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
}

Its a Bit operation!它是一个位操作!

if ((myFoo & (myFoo -1)) != 0) //has more than 1 flag

The statement checks if the value of myFoo is not power of two.该语句检查myFoo的值是否不是 2 的幂。 Or, vice versa, the statement (myFoo & (myFoo -1)) == 0 checks for power of two.或者,反之亦然,语句(myFoo & (myFoo -1)) == 0检查二的幂。 The idea is that only single flag values will be power of two.这个想法是只有单个标志值是二的幂。 Setting more than one flag will result in a non power of two value of myFoo .设置多个标志将导致myFoo值的非二次myFoo

More information can be found in this answer to a similar question: https://stackoverflow.com/a/1662162/2404788 .更多信息可以在这个对类似问题的回答中找到: https : //stackoverflow.com/a/1662162/2404788

For more information about bit operations go to http://en.wikipedia.org/wiki/Bitwise_operation有关位操作的更多信息,请访问http://en.wikipedia.org/wiki/Bitwise_operation

private bool ExatlyOneFlagSet(Foo myFoo)
{
  return !myFoo.ToString().Contains(',');
}

If the enum doesn't define explicit combinations of flags, you can just check if the value is defined in the enum:如果枚举没有定义明确的标志组合,您可以检查枚举中是否定义了该值:

private bool ExactlynOneFlagSet(Foo myFoo)
{
    return Enum.IsDefined(typeof(Foo), myFoo);
}

If you're using .NET Core 3.0+, you can use PopCount , it returns the number of "1" bits in a uint or ulong and uses the POPCNT CPU instruction (if CPU supports SSE4, otherwise it'll use a software fallback).如果您使用 .NET Core 3.0+,则可以使用PopCount ,它返回uintulong中“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

As Jacob explained in a comment your method is not correct at all.正如雅各布在评论中解释的那样,您的方法根本不正确。 Personally I always avoid programming mathematically, especially when it comes to logic.就我个人而言,我总是避免进行数学编程,尤其是在逻辑方面。 So my solution would be something like "if I wanted to know the count is one, so count it and compare it to number one".因此,我的解决方案类似于“如果我想知道计数为 1,则对其进行计数并将其与第一进行比较”。

Here it is:这里是:

    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;
    }

And you can use it for your foo type like this:你可以像这样将它用于你的 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);

I believe this methods could be written in a more generic way using Generics and type handling methods.我相信可以使用泛型和类型处理方法以更通用的方式编写这些方法。 However I included the methods for most common base types for enums which are int and byte.但是,我包括了最常见的枚举基本类型的方法,这些方法是 int 和 byte。 But you could also write the same for short and other types.但是您也可以为 short 和其他类型编写相同的代码。 Also you may just inline the code in your code.您也可以在代码中内联代码。 It is only one line of code.它只有一行代码。

Also using this method you could see if the number of set flags is two or more.同样使用此方法,您可以查看设置标志的数量是否为两个或更多。 The below code returns true if the count of set flags is equal to 'n'.如果设置标志的计数等于“n”,则以下代码返回 true。

   Enum.GetValues(enumType).Cast<byte>().Count(v => (value & v) == v) == n;

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM