测试按位枚举值

Mr *_*ose 17 c# comparison enums bit-manipulation bit

我以前没有真正使用过按位枚举,我只是想确保我的测试是正确的.我最感兴趣的是测试值None和All.我们从使用此枚举的Web服务接收数据,以对某些数据进行分类.鉴于此,我假设nether None和All将与任何其他值组合.

给出以下按位枚举定义;

[System.FlagsAttribute()]
public enum TrainingComponentTypes : int
    {
        None = 0,
        AccreditedCourse = 1,
        Qualification = 2,
        Unit = 4,
        SkillSet = 8,
        UnitContextualisation = 16,
        TrainingPackage = 32,
        AccreditedCourseModule = 64,
        All = 127,
    }
Run Code Online (Sandbox Code Playgroud)

我在这个MSDN网站上阅读了关于FlagAttributes 的以下引用;

使用None作为其值为零的标志枚举常量的名称.您不能在按位AND运算中使用None枚举常量来测试标志,因为结果始终为零.但是,您可以在数值和None枚举常量之间执行逻辑而非按位比较,以确定是否设置了数值中的任何位.

此实例中的逻辑比较是否指向枚举的正常相等性测试?例如;

TrainingComponentTypes tct = TrainingComponentTypes.None; 
if (tct == TrainingComponentTypes.None) 
{ ... }
Run Code Online (Sandbox Code Playgroud)

为了进行逐位比较,我正在执行以下操作;

 TrainingComponentTypes tct = TrainingComponentTypes.AccreditedCourse | TrainingComponentTypes.Qualification | TrainingComponentTypes.TrainingPackage;
 Assert.IsTrue((tct & TrainingComponentTypes.AccreditedCourse) == TrainingComponentTypes.AccreditedCourse, "Expected AccreditedCourse as part the enum");

 Assert.IsFalse((tct & TrainingComponentTypes.SkillSet) == TrainingComponentTypes.SkillSet, "Found unexpected SkillSet as part the enum");
Run Code Online (Sandbox Code Playgroud)

最后,在测试所有内容时,我尝试了逻辑和按位比较,并且它们都返回相同的内容.我应该在这里使用一个吗?例如;

TrainingComponentTypes tct = TrainingComponentTypes.All;

Assert.IsTrue((tct & TrainingComponentTypes.All) == TrainingComponentTypes.All, "Expected All as part the enum");
Assert.IsTrue((tct) == TrainingComponentTypes.All, "Expected All as part the enum");
// The follow also pass the assertion for a value of All
Assert.IsTrue((tct & TrainingComponentTypes.Qualification) == TrainingComponentTypes.Qualification, "Expected Qualification as part the enum");
Assert.IsTrue((tct & TrainingComponentTypes.TrainingPackage) == TrainingComponentTypes.TrainingPackage, "Expected TrainingPackage as part the enum");
Run Code Online (Sandbox Code Playgroud)

总而言之,我想知道关于Bitwise枚举的以下内容;

  1. 鉴于上面的例子,我对逻辑比较的理解是否正确?
  2. 我执行按位比较的方式是否正确?
  3. 处理"全部"值(按位或逻辑)的正确方法是什么.我不确定我们是否会收到一个值,其中All与其他TrainingComponentTypes结合使用.我不明白为什么会这样,但是,你永远都不知道?
  4. 我是否正确地假设switch语句基本上不应该用于按位枚举(给定none似乎是特殊情况并且需要逻辑比较)?

谢谢,克里斯

por*_*ges 17

简答:是的:)

更长:

1)所有操作都是在flags变量的整数值上执行的,因此您可以根据这一点考虑它们.

2)是的.

3)要么有效.但是,值得注意的是,如果有人将无效值推入变量,则== TrainingComponentTypes.All版本将失败.例如:

var badValue = (TrainingComponentTypes)128 | TrainingComponentTypes.All;
// now badValue != TrainingComponentTypes.All
// but (badValue & TrainingComponentTypes.All) == TrainingComponentTypes.All
Run Code Online (Sandbox Code Playgroud)

对于这部分:

我不确定我们是否会收到一个值,其中All与其他TrainingComponentTypes结合使用.

我不确定你是否完全理解枚举是如何运作的.

The value of All is:
    127 = 1111111 (binary)

The other values are:
    AccreditedCourse       = 0000001
    Qualification          = 0000010
    Unit                   = 0000100
    SkillSet               = 0001000
    UnitContextualisation  = 0010000
    TrainingPackage        = 0100000
    AccreditedCourseModule = 1000000
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,All只是|所有这些值的按位.您不能将任何其他TraningComponentTypes与All结合使用,因为All已经包含它们!此外,如果将它们与|自己组合在一起,它与直接使用All完全相同(因此,在枚举中定义它时,All只是一种方便).

4)您可以使用它来检查None或All,但不能检查其他值.

值得注意的是,Enum上有一种方便的方法可以为你做这些检查:Enum.HasFlag.


Ric*_*key 8

鉴于上面的例子,我对逻辑比较的理解是否正确?

是的,在这种情况下,逻辑意味着运营商的平等和不平等.

我执行按位比较的方式是否正确?

是的,但有一种更简单的方法:Enum.HasFlag.例如:

tct.HasFlag(TrainingComponentTypes.Qualification)
Run Code Online (Sandbox Code Playgroud)

代替:

(tct & TrainingComponentTypes.Qualification) == TrainingComponentTypes.Qualification
Run Code Online (Sandbox Code Playgroud)

处理"全部"值(按位或逻辑)的正确方法是什么.我不确定我们是否会收到一个值,其中All与其他TrainingComponentTypes结合使用.我不明白为什么会这样,但是,你永远都不知道?

我认为最好Allenum自身定义为其所有部分的按位OR.但是你会看到人们都是这样做的.

我是否正确地假设switch语句基本上不应该用于按位枚举(给定none似乎是特殊情况并且需要逻辑比较)?

一点都不.随意使用它们是switch陈述.该case值必须是常量,但他们可以表达和平等的测试.编译器会告诉你是否做了一些愚蠢的事情,比如尝试case两次使用相同的值.

  • `Enum.HasFlag` 在第一次添加时非常缓慢,但后来得到了改进。另请参阅此 [答案](http://stackoverflow.com/a/7368674/553613) (2认同)