Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Check if an enum flag contains a certain flag value

In C# (using Unity working on a game) I have an enum with the [Flag] attribute. I have instantiated it twice. I would like a way to compare the two enums. Specifically if enum A (which will have multiple flags) contains a flag from enum B (which will only ever be assigned a single flag).

I am not trying to compare a single instantiated enum to a single flag (this has been answered multiple times).

I suspect I could do this by dumping values with GetValue and comparing those values on a foreach loop, but it seems like there should be a more direct way to compare.

public enum AbilityType
{
    None = 0,
    Pierce = 1<<1,
    Blunt = 1<<2,
    Slash = 1<<3,
    Water = 1<<4,
    // etc.
};


public class Ability : MonoBehaviour
{
    public AbilityType abilityType;
}

public class AbilitiedObject : StatisticalObject
{
    public AbilityType resistances;

    protected override void Awake()
    {
        base.Awake();
        resistances = AbilityType.Pierce | AbilityType.Water;
    }

    public void TakeDamage(int damageAmount, AbilityType abilityType)
    {
        if( ) // Check if resistances contains abilityType's flag here
        {
            print("You are resistance to this damage type");
        }
        else
        {
            // Player takes damage
        }
    }
}

I'd like the above code to check if resistances contains the flag from abilityType. In the example above, the attack in question will pass it's abilityType in. If that type is water or pierce, it should print the resistance statement. If it's another type, it should deal damage as normal.

like image 763
George Barron Avatar asked Dec 23 '22 22:12

George Barron


1 Answers

What you want is to abuse, as stated in the comments and other answers, is the bitwise & operator to compare as enums are (by default) based on the int type. However since .NET 4.0 there has been the addition of Enum.HasFlag extension method that does exactly this and increases readability.

// These two are semantically equal

if (resistance.HasFlag(abilityType))
{
    print("You are resistance to this damage type");
}

if ((resistance & abilityType) != 0)
{
    print("You are resistance to this damage type");
}

Behind the scenes of this is explained by numerous others. Can personally recommend Alan Zucconi's Enum, Flags and bitwise operators

Short version is that the bitwise AND (&) operator gives a result of where two values "match" in the sense that they're both active, bit by bit. One way to think of it is as a selective filter. To check if a value A of unknown flag set contains a specific flag B, you use the filter which only allows flag B to pass through and check if anything got through, where anything is represented as anything else than zero. The filter is simply the same as the flag you wish to look for. Therefore the expression becomes (A & B) != 0. Parentheses to force override order of operations since != has higher precedence than &.

like image 126
Applejag Avatar answered Dec 30 '22 10:12

Applejag