测试多个标志值

Testing for multiple flag values

我有这个标志枚举:

public enum AssignmentType
{
    None = 0,
    Attendant = 1,
    ConductorCBS = 2,
    ReaderCBS = 4,
    Chairman = 8,
    Mike = 16,
    PlatformAttendant = 32,
    Prayer = 64,
    OCLM = 128,
    Sound = 256,
    Student = 512,
    Custom = 1024,
    Demonstration = 2048,
    Assistant = 4096
}

我现在想针对某个标志条件测试我的变量。

我想确定我的变量是只是的任意组合:

因此,如果它具有任何其他枚举值,则该变量将不满足测试。

起初我是这样开始的:

bool bIsPersonnel = true;

if (_Assignments == AssignmentType.None ||
    _Assignments == AssignmentType.Demonstration || 
    _Assignments == AssignmentType.Student ||
    _Assignments == AssignmentType.Assistant ||
    _Assignments == (AssignmentType.Demonstration | AssignmentType.Student))
{
    bIsPersonnel = false;
}

但我很快意识到有多种选择。

有没有更简单的方法?

我看不出建议的答案有什么帮助。我想反向进行测试是最简单的。只要测试它是否有任何其他标志然后我就知道它是人员!

(答案不正确)

if ((_Assignments & AssignmentType.None) > 0
    || (_Assignments & AssignmentType.Student) > 0
    || (_Assignments & AssignmentType.Assistant) > 0
    || (_Assignments & AssignmentType.Demonstration) > 0
){
    bIsPersonnel = false;
}

更正答案:

var NonPersonnel = AssignmentType.None | AssignmentType.Student | AssignmentType.Assistant | Demonstration;
bool bIsPersonnel = (_Assignments | NonPersonnel) != NonPersonnel;

目前我想到了做反向测试:

bool bIsPersonnel = false;

if(_Assignments.HasFlag(AssignmentType.Attendant | AssignmentType.ConductorCBS |
    AssignmentType.ReaderCBS | AssignmentType.Chairman |
    AssignmentType.Mike | AssignmentType.PlatformAttendant |
    AssignmentType.Prayer | AssignmentType.OCLM |
    AssignmentType.Sound | AssignmentType.Custom))
{
    bIsPersonnel = true;
}

这是最简单的,因为我们知道如果设置了这些标志中的任何一个,那么这个人就是 "Personnel"。其他标志不在画面中,我们不必测试多个标志配置。

您可以使用 ~ 按位否定运算符应用掩码来查找所有 无效 标志,并检查是否已应用任何标志。

var valid = AssignmentType.Student | AssignmentType.Assistant | AssignmentType.Demonstration;
var invalid = ~valid; // Everything that isn't valid

if ((_Assignments & invalid) != 0)
{
    // There was at least one invalid flag, handle it appropriately
}

或者检查是否有效:

if ((_Assignment & invalid) == 0)
{
    // There are no invalid flags, handle it appropriately
}

或者,如果您刚刚设置了一个布尔标志,则根本不需要 if 语句:

bool isPersonnel = ((assignment & invalid) != 0);

只需制作一个要检查的值的掩码,and 带有值的掩码,这就是检查标志的方式,而不管标志的数量如何

if (0 != _Assignments &
     (AssignmentType.Demonstration | AssignmentType.Student | AssignmentType.Assistant))

不需要检查AssignmentType.None,因为它本身不是标志,只是一个等于0的保留值,用于检查标志的none是否已设置。如果组合同时包含 "no flag" 和 "some other flag" 那么它就没有意义,对吧?如果您确实需要检查 "no flag" 条件,请单独检查

if (_Assignments == AssignmentType.None || (0 != _Assignments &
         (AssignmentType.Demonstration | AssignmentType.Student | AssignmentType.Assistant)))

这也是 Enum.HasFlag() 检查标志的方式

public static void Main()
{
   DinnerItems myOrder = DinnerItems.Appetizer | DinnerItems.Entree |
                        DinnerItems.Beverage | DinnerItems.Dessert;
   DinnerItems flagValue = DinnerItems.Entree | DinnerItems.Beverage;
   Console.WriteLine("{0} includes {1}: {2}", 
                     myOrder, flagValue, myOrder.HasFlag(flagValue));
}

我认为这符合预期:

var flags =
    AssignmentType.None
    | AssignmentType.Student
    | AssignmentType.Assistant
    | AssignmentType.Demonstration;

bool bIsPersonnel =
    !(_Assignments == AssignmentType.None
        || (flags & _Assignments) == _Assignments);

这是一些示例输出:

_Assignments = AssignmentType.Demonstration | AssignmentType.Assistant; // False
_Assignments = AssignmentType.None; // False
_Assignments = AssignmentType.Demonstration | AssignmentType.Mike; // True