How to Compare Flags in C#?

前端 未结 11 1714
我寻月下人不归
我寻月下人不归 2020-11-27 04:03

I have a flag enum below.

[Flags]
public enum FlagTest
{
    None = 0x0,
    Flag1 = 0x1,
    Flag2 = 0x2,
    Flag3 = 0x4
}

I cannot make

相关标签:
11条回答
  • 2020-11-27 04:06

    even without [Flags], you could use something like this

    if((testItem & (FlagTest.Flag1 | FlagTest.Flag2 ))!=0){
    //..
    }
    

    or if you have a Zero value enum

    if((testItem & (FlagTest.Flag1 | FlagTest.Flag2 ))!=FlagTest.None){
    //..
    }
    
    0 讨论(0)
  • 2020-11-27 04:12
    if ((testItem & FlagTest.Flag1) == FlagTest.Flag1)
    {
         // Do something
    }
    

    (testItem & FlagTest.Flag1) is a bitwise AND operation.

    FlagTest.Flag1 is equivalent to 001 with OP's enum. Now let's say testItem has Flag1 and Flag2 (so it's bitwise 101):

      001
     &101
     ----
      001 == FlagTest.Flag1
    
    0 讨论(0)
  • 2020-11-27 04:16

    For those who have trouble visualizing what is happening with the accepted solution (which is this),

    if ((testItem & FlagTest.Flag1) == FlagTest.Flag1)
    {
        // Do stuff.
    }
    

    testItem (as per the question) is defined as,

    testItem 
     = flag1 | flag2  
     = 001 | 010  
     = 011
    

    Then, in the if statement, the left hand side of the comparison is,

    (testItem & flag1) 
     = (011 & 001) 
     = 001
    

    And the full if statement (that evaluates to true if flag1 is set in testItem),

    (testItem & flag1) == flag1
     = (001) == 001
     = true
    
    0 讨论(0)
  • 2020-11-27 04:19

    In .NET 4 there is a new method Enum.HasFlag. This allows you to write:

    if ( testItem.HasFlag( FlagTest.Flag1 ) )
    {
        // Do Stuff
    }
    

    which is much more readable, IMO.

    The .NET source indicates that this performs the same logic as the accepted answer:

    public Boolean HasFlag(Enum flag) {
        if (!this.GetType().IsEquivalentTo(flag.GetType())) {
            throw new ArgumentException(
                Environment.GetResourceString(
                    "Argument_EnumTypeDoesNotMatch", 
                    flag.GetType(), 
                    this.GetType()));
        }
    
        ulong uFlag = ToUInt64(flag.GetValue()); 
        ulong uThis = ToUInt64(GetValue());
        // test predicate
        return ((uThis & uFlag) == uFlag); 
    }
    
    0 讨论(0)
  • 2020-11-27 04:21

    One more piece of advice... Never do the standard binary check with the flag whose value is "0". Your check on this flag will always be true.

    [Flags]
    public enum LevelOfDetail
    {
        [EnumMember(Value = "FullInfo")]
        FullInfo=0,
        [EnumMember(Value = "BusinessData")]
        BusinessData=1
    }
    

    If you binary check input parameter against FullInfo - you get:

    detailLevel = LevelOfDetail.BusinessData;
    bool bPRez = (detailLevel & LevelOfDetail.FullInfo) == LevelOfDetail.FullInfo;
    

    bPRez will always be true as ANYTHING & 0 always == 0.


    Instead you should simply check that the value of the input is 0:

    bool bPRez = (detailLevel == LevelOfDetail.FullInfo);
    
    0 讨论(0)
  • 2020-11-27 04:22

    I set up an extension method to do it: related question.

    Basically:

    public static bool IsSet( this Enum input, Enum matchTo )
    {
        return ( Convert.ToUInt32( input ) & Convert.ToUInt32( matchTo ) ) != 0;
    }
    

    Then you can do:

    FlagTests testItem = FlagTests.Flag1 | FlagTests.Flag2;
    
    if( testItem.IsSet ( FlagTests.Flag1 ) )
        //Flag1 is set
    

    Incidentally the convention I use for enums is singular for standard, plural for flags. That way you know from the enum name whether it can hold multiple values.

    0 讨论(0)
提交回复
热议问题