检查枚举标志是否包含某个标志值

Dra*_*ron 2 c# enums unity-game-engine enum-flags

在 C# 中(使用 Unity 处理游戏)我有一个带有 [Flag] 属性的枚举。我已经实例化了两次。我想要一种比较两个枚举的方法。特别是如果 enum A(将有多个标志)包含来自 enum 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;
}
Run Code Online (Sandbox Code Playgroud)

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
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

我想要上面的代码来检查电阻是否包含来自能力类型的标志。在上面的例子中,有问题的攻击将传入它的能力类型。如果该类型是水或穿刺,它应该打印阻力声明。如果是其他类型,它应该会正常造成伤害。

App*_*jag 6

正如评论和其他答案中所述,您想要滥用的是按位运算&符进行比较,因为枚举(默认情况下)基于int类型。但是,从 .NET 4.0 开始,添加了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");
}
Run Code Online (Sandbox Code Playgroud)

许多其他人对此进行了解释。可以个人推荐Alan Zucconi 的 Enum, Flags 和 bitwise operators

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