Enum.HasFlag 中的意外结果
Unexpected result in Enum.HasFlag
我最近在我的代码中遇到了一个错误,我试图将一个枚举标志 "dismantle" 放入其组成值的数组中,但有时会返回意外的结果。
长话短说,分配给我的值的某些整数类型似乎会导致一些意外行为(好吧,至少对我来说是这样)。我将问题归结为以下单元测试:
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
会报告它 "has the flag" of ITEM1
,因为我不相信它确实如此。
我猜这与我分配给项目的 Int32 值有关,但请有人解释一下这是怎么回事吗? - 为什么这个测试失败了?
基本上,您不应该将 HasFlag
用于非基于标志的枚举...并且基于标志的枚举应该为每个标志使用单独的位。
确实是价值观的问题。用二进制写这个,你有:
public enum TestEnum
{
ITEM1 = 0b111010110011000,
ITEM2 = 0b111010111111001
}
请注意 ITEM1
中设置的每一位也在 ITEM2
中设置 - 这就是 HasFlag
检查的内容。来自 documentation:
Returns:
true
if the bit field or bit fields that are set in flag
are also set in the current instance; otherwise, false
.
对于 TestEnum.ITEM2.HasFlag(TestEnum.Item1)
, 为真,因此 returns 为真。
HasFlag
方法是按位检查,ITEM1
的位与 ITEM2
匹配:
请注意 ITEM2
包含与 ITEM1
相同的 1
:
ITEM1: 111010110011000
ITEM2: 111010111111001
您似乎想使用 "Bit flags" - 易于合并的布尔值集合。
为此,每个标志都需要设置一位,并且该位需要位于唯一的位置。
但是组合标志以涵盖常见分组是有效的。
我在 Whosebug 上学到的一项技术是设置第一个标志,然后对其余标志进行位移。像这样:
[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));
我希望这能帮您解决问题![=12=]
- 注意,这里的代码主要是伪代码;可能有语法错误。然而,这个概念是合理的。
我最近在我的代码中遇到了一个错误,我试图将一个枚举标志 "dismantle" 放入其组成值的数组中,但有时会返回意外的结果。
长话短说,分配给我的值的某些整数类型似乎会导致一些意外行为(好吧,至少对我来说是这样)。我将问题归结为以下单元测试:
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
会报告它 "has the flag" of ITEM1
,因为我不相信它确实如此。
我猜这与我分配给项目的 Int32 值有关,但请有人解释一下这是怎么回事吗? - 为什么这个测试失败了?
基本上,您不应该将 HasFlag
用于非基于标志的枚举...并且基于标志的枚举应该为每个标志使用单独的位。
确实是价值观的问题。用二进制写这个,你有:
public enum TestEnum
{
ITEM1 = 0b111010110011000,
ITEM2 = 0b111010111111001
}
请注意 ITEM1
中设置的每一位也在 ITEM2
中设置 - 这就是 HasFlag
检查的内容。来自 documentation:
Returns:
true
if the bit field or bit fields that are set inflag
are also set in the current instance; otherwise,false
.
对于 TestEnum.ITEM2.HasFlag(TestEnum.Item1)
, 为真,因此 returns 为真。
HasFlag
方法是按位检查,ITEM1
的位与 ITEM2
匹配:
请注意 ITEM2
包含与 ITEM1
相同的 1
:
ITEM1: 111010110011000
ITEM2: 111010111111001
您似乎想使用 "Bit flags" - 易于合并的布尔值集合。
为此,每个标志都需要设置一位,并且该位需要位于唯一的位置。
但是组合标志以涵盖常见分组是有效的。
我在 Whosebug 上学到的一项技术是设置第一个标志,然后对其余标志进行位移。像这样:
[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));
我希望这能帮您解决问题![=12=]
- 注意,这里的代码主要是伪代码;可能有语法错误。然而,这个概念是合理的。