检查枚举标志是否包含特定标志值

Check if an enum flag contains a certain flag value

在 C# 中(使用 Unity 开发游戏)我有一个带有 [Flag] 属性的枚举。我已经实例化了两次。我想要一种方法来比较这两个枚举。特别是如果枚举 A(将有多个标志)包含一个来自枚举 B 的标志(它只会被分配一个标志)。

不是试图将单个实例化枚举与单个标志进行比较(这已被多次回答)。

我怀疑我可以通过使用 GetValue 转储值并在 foreach 循环中比较这些值来做到这一点,但似乎应该有更直接的比较方法。

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

我想用上面的代码检查 resistances 是否包含来自 abilityType 的标志。在上面的示例中,有问题的攻击将传递它的能力类型。如果该类型是水或刺穿,它应该打印抵抗声明。如果是另一种类型,它应该会造成正常伤害。

这是您需要的:

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

正如评论和其他答案中所述,您想要的是滥用按位 & 运算符进行比较,因为枚举是 (by default) based on the int type. However since .NET 4.0 there has been the addition of Enum.HasFlag 扩展方法,它正是这样做并提高了可读性。

// 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");
}

很多人都在幕后解释了这一点。可以个人推荐Alan Zucconi's Enum, Flags and bitwise operators

简而言之,按位与 (&) 运算符给出了两个值 "match" 的结果,因为它们都处于活动状态,一点一点。一种将其视为选择性过滤器的方法。要检查未知标志集的值 A 是否包含特定标志 B,您可以使用只允许标志 B 通过的过滤器,并检查是否有任何东西通过,什么东西是表示为除零以外的任何值。过滤器与您要查找的标志完全相同。因此表达式变为 (A & B) != 0。括号强制覆盖操作顺序,因为 != 的优先级高于 &.