我最近在我的代码中遇到了一个错误,我试图"拆除"将枚举标志放入其组成值的数组中,但有时会返回意外结果。
长话短说,分配给我的值的某些整数类型似乎会导致一些意外的行为(至少对我来说)。我将问题归结为以下单元测试:
public enum TestEnum
{
ITEM1 = 30104,
ITEM2 = 30201,
}
[TestClass]
public class EnumFlagTest
{
[TestMethod]
public void SanityCheck()
{
var flag2 = TestEnum.ITEM2;
Assert.IsFalse(flag2.HasFlag(TestEnum.ITEM1));
}
}
我没想到flag2
会报告它有#34;有标志"是ITEM1
,因为我不相信它。
我想这与我分配给这些项目的Int32值有关,但请有人解释一下发生了什么? - 为什么这个测试失败了?
答案 0 :(得分:5)
基本上,你不应该使用HasFlag
作为非基于标志的枚举...而基于标志的枚举应该为每个标志使用一个单独的位。
问题确实是因为价值观。用二进制文写这个,你得到了:
public enum TestEnum
{
ITEM1 = 0b111010110011000,
ITEM2 = 0b111010111111001
}
请注意ITEM1
中设置的每个位如何也在ITEM2
中设置 - 这是HasFlag
检查的内容。来自documentation:
返回:
true
如果在flag
中设置的位字段或位字段也在当前实例中设置;否则,false
。
TestEnum.ITEM2.HasFlag(TestEnum.Item1)
的 为真,因此返回true。
答案 1 :(得分:2)
HasFlag
方法是按位检查,ITEM1
的位与ITEM2
匹配:
请注意,ITEM2
包含1
所拥有的所有ITEM1
:
ITEM1: 111010110011000
ITEM2: 111010111111001
答案 2 :(得分:1)
看起来你想要使用“Bit flags” - 一组易于合并的布尔值。
为此,每个标志需要设置一个位,并且该位需要位于唯一的位置。
但是将标志组合起来以涵盖常见的分组是有效的。
我在StackOverflow上学到的一种技术是设置第一个标志,然后为其余标志进行位移。像这样:
[Flags]
enum color {
none = 0,
red = 1, // 0b0001
yellow = red << 1, // 0b0010
blue = yellow << 1, // 0b0100
primaries = red | yellow | blue, // 0b0111
green = yellow | blue, // 0b0110
purple = red | blue, // 0b0101
orange = red | yellow // 0b0011
}
有了这个,你可以
Assert.IsFalse(Color.green.HasFlag(color.red));
Assert.IsTrue(Color.primary.HasFlag(color.red));
我希望能为你解决问题!