【问题标题】:Check if an enum flag contains a certain flag value检查枚举标志是否包含某个标志值
【发布时间】:2019-06-16 17:49:28
【问题描述】:

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

我希望上面的代码检查阻力是否包含来自能力类型的标志。在上面的示例中,所讨论的攻击将传递它的能力类型。如果该类型是水或穿刺,它应该打印抵抗声明。如果是其他类型,它应该正常造成伤害。

【问题讨论】:

  • SO Article 对您有用吗?听起来你想要按位运算。像这样if(resistances &amp; abilityType == abilityType)...不是在电脑上。
  • 不要试图听起来专横,但标志在互联网上被广泛记录。你可以谷歌“flag c#”,你很可能会找到一个快速的答案。
  • Most common C# bitwise operations on enums 的可能重复项。从字面上看,最佳答案有你想要的。
  • @DrakeBarron “两个枚举”和“一个枚举和一个标志”之间没有任何区别。
  • 顺便说一下(a &amp; b) != 0(a &amp; b) == b 的区别在于,第一个检查b 的标志中的any 是否设置在@ 987654329@,第二个检查是否设置了所有个。

标签: c# unity3d enums enum-flags


【解决方案1】:

如 cmets 和其他答案中所述,您想要滥用的是按位 &amp; 运算符来比较,因为枚举是基于 int 类型的 (by default)。但是,从 .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");
}

许多其他人解释了这件事的幕后。可以个人推荐Alan Zucconi's Enum, Flags and bitwise operators

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

【讨论】:

  • Enum.HasFlag() 仅适用于标有FlagsAttribute 属性的枚举类型
【解决方案2】:

这是你需要的:

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

【讨论】:

  • 在这种情况下,这似乎是正确的。在更一般的意义上,可能存在 combine 标志的值。在这里,如果resistances 包含Water 但不包含Slashingresistances &amp; AbilityType.SlashingWater 将非零,因此您将返回误报。 (通常)提出的问题是:“resistances 包含 abilityType 指定的标志吗?”您的实现回答的问题是:“resistances 是否包含至少一个abilityType 指定的标志?”要回答前者,更常见的问题:(resistances &amp; abilityType) == abilityType
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-22
  • 1970-01-01
相关资源
最近更新 更多