C# 如何检查是否设置了标志组合的任何标志?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/1339976/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 15:20:07  来源:igfitidea点击:

How to check if any flags of a flag combination are set?

c#enumsflags

提问by Svish

Let's say I have this enum:

假设我有这个枚举:

[Flags]
enum Letters
{
     A = 1,
     B = 2,
     C = 4,
     AB = A | B,
     All = A | B | C,
}

To check if for example ABis set I can do this:

要检查例如AB是否设置,我可以这样做:

if((letter & Letters.AB) == Letters.AB)

Is there a simpler way to check if any of the flags of a combined flag constant are set than the following?

是否有比以下更简单的方法来检查是否设置了组合标志常量的任何标志?

if((letter & Letters.A) == Letters.A || (letter & Letters.B) == Letters.B)

Could you for example swap the &with something?

例如,你可以&用什么东西交换吗?

Not too stable when it comes to binary stuff like this...

当涉及到像这样的二进制东西时不太稳定......

采纳答案by yeyeyerman

If you want to know if letter has any of the letters in AB you must use the AND& operator. Something like:

如果您想知道 letter 是否包含 AB 中的任何字母,则必须使用AND& 运算符。就像是:

if ((letter & Letters.AB) != 0)
{
    // Some flag (A,B or both) is enabled
}
else
{
    // None of them are enabled
}

回答by Lee

if((int)letter != 0) { }

回答by Jakob Christensen

How about

怎么样

if ((letter & Letters.AB) > 0)

?

?

回答by Tamas Czinege

If it really annoys you, you can write a function like that:

如果它真的让你烦恼,你可以写一个这样的函数:

public bool IsSet(Letters value, Letters flag)
{
    return (value & flag) == flag;
}

if (IsSet(letter, Letters.A))
{
   // ...
}

// If you want to check if BOTH Letters.A and Letters.B are set:
if (IsSet(letter, Letters.A & Letters.B))
{
   // ...
}

// If you want an OR, I'm afraid you will have to be more verbose:
if (IsSet(letter, Letters.A) || IsSet(letter, Letters.B))
{
   // ...
}

回答by Sebastiaan M

Would this work for you?

这对你有用吗?

if ((letter & (Letters.A | Letters.B)) != 0)

Regards,

问候,

Sebastiaan

塞巴斯蒂安

回答by Will

To check if for example AB is set I can do this:

if((letter & Letters.AB) == Letters.AB)

Is there a simpler way to check if any of the flags of a combined flag constant are set than the following?

要检查是否设置了 AB,我可以这样做:

如果((字母和字母.AB)==字母.AB)

是否有比以下更简单的方法来检查是否设置了组合标志常量的任何标志?

This checks that bothA and B are set, and ignores whether any other flags are set.

这将检查两个A和B设置,以及是否忽略任何其他标志被设置。

if((letter & Letters.A) == Letters.A || (letter & Letters.B) == Letters.B)
if((letter & Letters.A) == Letters.A || (letter & Letters.B) == Letters.B)

This checks that eitherA or B is set, and ignores whether any other flags are set or not.

这个检查或者A或B被设置,并且是否忽略任何其他标志被设定或没有。

This can be simplified to:

这可以简化为:

if(letter & Letters.AB)

Here's the C for binary operations; it should be straightforward to apply this to C#:

这是用于二元运算的 C;将其应用于 C# 应该很简单:

enum {
     A = 1,
     B = 2,
     C = 4,
     AB = A | B,
     All = AB | C,
};

int flags = A|C;

bool anything_and_a = flags & A;

bool only_a = (flags == A);

bool a_and_or_c_and_anything_else = flags & (A|C);

bool both_ac_and_anything_else = (flags & (A|C)) == (A|C);

bool only_a_and_c = (flags == (A|C));

Incidentally, the naming of the variable in the question's example is the singular 'letter', which might imply that it represents only a single letter; the example code makes it clear that its a set of possible letters and that multiple values are allowed, so consider renaming the variable 'letters'.

顺便提一下,问题示例中变量的命名是单数“字母”,这可能意味着它只代表一个字母;示例代码清楚地表明它是一组可能的字母并且允许多个值,因此请考虑重命名变量“字母”。

回答by Daniel Brückner

You could just check if the value is not zero.

您可以检查该值是否不为零。

if ((Int32)(letter & Letters.AB) != 0) { }

But I would consider it a better solution to introduce a new enumeration value with value zero and compare agains this enumeration value (if possible because you must be able to modify the enumeration).

但我认为引入一个零值的新枚举值并再次比较这个枚举值是一个更好的解决方案(如果可能,因为您必须能够修改枚举)。

[Flags]
enum Letters
{
    None = 0,
    A    = 1,
    B    = 2,
    C    = 4,
    AB   =  A | B,
    All  = AB | C
}

if (letter != Letters.None) { }

UPDATE

更新

Missread the question - fixed the first suggestion and just ignore the second suggestion.

误读了问题 - 修正了第一个建议,而忽略了第二个建议。

回答by stevehipwell

There are two aproaches that I can see that would work for checking for any bit being set.

我可以看到有两种方法可以用于检查是否设置了任何位。

Aproach A

方法A

if (letter != 0)
{
}

This works as long as you don't mind checking for allbits, including non-defined ones too!

只要您不介意检查所有位(包括未定义的位),此方法就有效!

Aproach B

方法B

if ((letter & Letters.All) != 0)
{
}

This only checks the defined bits, as long as Letters.All represents all of the possible bits.

这仅检查定义的位,只要 Letters.All 代表所有可能的位。

For specific bits (one or more set), use Aproach B replacing Letters.All with the bits that you want to check for (see below).

对于特定位(一组或多组),使用方法 B 将 Letters.All 替换为您要检查的位(见下文)。

if ((letter & Letters.AB) != 0)
{
}

回答by Thomas Levesque

I use extension methods to write things like that :

我使用扩展方法来写这样的东西:

if (letter.IsFlagSet(Letter.AB))
    ...

Here's the code :

这是代码:

public static class EnumExtensions
{
    private static void CheckIsEnum<T>(bool withFlags)
    {
        if (!typeof(T).IsEnum)
            throw new ArgumentException(string.Format("Type '{0}' is not an enum", typeof(T).FullName));
        if (withFlags && !Attribute.IsDefined(typeof(T), typeof(FlagsAttribute)))
            throw new ArgumentException(string.Format("Type '{0}' doesn't have the 'Flags' attribute", typeof(T).FullName));
    }

    public static bool IsFlagSet<T>(this T value, T flag) where T : struct
    {
        CheckIsEnum<T>(true);
        long lValue = Convert.ToInt64(value);
        long lFlag = Convert.ToInt64(flag);
        return (lValue & lFlag) != 0;
    }

    public static IEnumerable<T> GetFlags<T>(this T value) where T : struct
    {
        CheckIsEnum<T>(true);
        foreach (T flag in Enum.GetValues(typeof(T)).Cast<T>())
        {
            if (value.IsFlagSet(flag))
                yield return flag;
        }
    }

    public static T SetFlags<T>(this T value, T flags, bool on) where T : struct
    {
        CheckIsEnum<T>(true);
        long lValue = Convert.ToInt64(value);
        long lFlag = Convert.ToInt64(flags);
        if (on)
        {
            lValue |= lFlag;
        }
        else
        {
            lValue &= (~lFlag);
        }
        return (T)Enum.ToObject(typeof(T), lValue);
    }

    public static T SetFlags<T>(this T value, T flags) where T : struct
    {
        return value.SetFlags(flags, true);
    }

    public static T ClearFlags<T>(this T value, T flags) where T : struct
    {
        return value.SetFlags(flags, false);
    }

    public static T CombineFlags<T>(this IEnumerable<T> flags) where T : struct
    {
        CheckIsEnum<T>(true);
        long lValue = 0;
        foreach (T flag in flags)
        {
            long lFlag = Convert.ToInt64(flag);
            lValue |= lFlag;
        }
        return (T)Enum.ToObject(typeof(T), lValue);
    }

    public static string GetDescription<T>(this T value) where T : struct
    {
        CheckIsEnum<T>(false);
        string name = Enum.GetName(typeof(T), value);
        if (name != null)
        {
            FieldInfo field = typeof(T).GetField(name);
            if (field != null)
            {
                DescriptionAttribute attr = Attribute.GetCustomAttribute(field, typeof(DescriptionAttribute)) as DescriptionAttribute;
                if (attr != null)
                {
                    return attr.Description;
                }
            }
        }
        return null;
    }
}

回答by Chuck Kasabula

In .NET 4 you can use the Enum.HasFlag method:

在 .NET 4 中,您可以使用Enum.HasFlag 方法

using System;

[Flags] public enum Pet {
   None = 0,
   Dog = 1,
   Cat = 2,
   Bird = 4,
   Rabbit = 8,
   Other = 16
}

public class Example
{
   public static void Main()
   {
      // Define three families: one without pets, one with dog + cat and one with a dog only
      Pet[] petsInFamilies = { Pet.None, Pet.Dog | Pet.Cat, Pet.Dog };
      int familiesWithoutPets = 0;
      int familiesWithDog = 0;

      foreach (Pet petsInFamily in petsInFamilies)
      {
         // Count families that have no pets. 
         if (petsInFamily.Equals(Pet.None))
            familiesWithoutPets++;
         // Of families with pets, count families that have a dog. 
         else if (petsInFamily.HasFlag(Pet.Dog))
            familiesWithDog++;
      }
      Console.WriteLine("{0} of {1} families in the sample have no pets.", 
                        familiesWithoutPets, petsInFamilies.Length);   
      Console.WriteLine("{0} of {1} families in the sample have a dog.", 
                        familiesWithDog, petsInFamilies.Length);   
   }
}

The example displays the following output:

该示例显示以下输出:

//       1 of 3 families in the sample have no pets. 
//       2 of 3 families in the sample have a dog.