简体   繁体   English

Enum.HasFlag中出现意外结果

[英]Unexpected result in Enum.HasFlag

I recently encountered an error in my code where I was attempting to "dismantle" an enum flag into an array of its constituent values, but unexpected results would sometimes be returned. 我最近在我的代码中遇到了一个错误,我试图将枚举标志“拆除”到其组成值的数组中,但有时会返回意外的结果。

Long story short, certain integer types assigned to my values appear to cause some behaviour that is unexpected (well, to me at least). 长话短说,分配给我的值的某些整数类型似乎会导致一些意外的行为(至少对我来说)。 I boiled down the issue into the following unit test: 我将问题归结为以下单元测试:

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

I did not expect flag2 to report that it "has the flag" of ITEM1 , as I do not believe that it does. 我没想到flag2会报告它“有ITEM1的旗帜”,因为我不相信它。

I guess that it has something to do with the Int32 values I've assigned to the items, but please could someone explain what's going on?? 我想这与我分配给项目的Int32值有关,但请有人解释一下发生了什么? - Why does this test fail? - 为什么这个测试失败了?

Basically, you shouldn't use HasFlag for a non flags-based enum... and a flags-based enum should use a separate bit for each flag. 基本上,您不应该将HasFlag用于非基于标志的枚举...并且基于标志的枚举应该为每个标志使用单独的位。

The problem is indeed because of the values. 问题确实是因为价值观。 Writing this in binary, you've got: 用二进制文件写这个,你得到:

public enum TestEnum
{
    ITEM1 = 0b111010110011000,
    ITEM2 = 0b111010111111001
}

Note how every bit that's set in ITEM1 is also set in ITEM2 - and that's what's checked by HasFlag . 注意ITEM1中设置的每个位如何也在ITEM2设置 - 这就是HasFlag检查的HasFlag From the documentation : 文档

Returns: 返回:

true if the bit field or bit fields that are set in flag are also set in the current instance; 如果在flag中设置的位字段或位字段也在当前实例中设置,则为true否则为true otherwise, false . 否则, false

That is true for TestEnum.ITEM2.HasFlag(TestEnum.Item1) , hence it returns true. 对于TestEnum.ITEM2.HasFlag(TestEnum.Item1) 也是如此,因此它返回true。

The HasFlag method is a bitwise check and the bits of ITEM1 match up with ITEM2 : HasFlag方法是按位检查, ITEM1的位与ITEM2匹配:

Note that ITEM2 contains all the same 1 s that ITEM1 has: 请注意, ITEM2包含与ITEM1相同的所有1

ITEM1: 111010110011000
ITEM2: 111010111111001

It looks like you are wanting to use "Bit flags" - a collection of boolean values that are easy to merge. 看起来你想要使用“位标志” - 一组容易合并的布尔值。

To do that, each flag needs one bit set and the bit needs to be in a unique location. 为此,每个标志需要设置一个位,并且该位需要位于唯一的位置。

But it is valid to combine flags to cover common groupings. 但是将标志组合起来以涵盖常见的分组是有效的。

One technique I learned here on StackOverflow is to set the first flag and then bit-shift for the rest of the flags. 我在StackOverflow上学到的一种技术是设置第一个标志,然后为其余的标志进行位移。 Something like this: 像这样的东西:

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

with this, you can 有了这个,你可以

Assert.IsFalse(Color.green.HasFlag(color.red));
Assert.IsTrue(Color.primary.HasFlag(color.red));

I hope that clears things up for you! 我希望能为你解决问题!

  • Note, the code here is largely pseudo-code; 注意,这里的代码主要是伪代码; there may be syntax errors. 可能存在语法错误。 The concept is, however, sound. 然而,这个概念是合理的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM