Тестирование для нескольких значений флага - PullRequest
2 голосов
/ 31 марта 2019

У меня есть перечисление этого флага:

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
}

Теперь я хочу проверить мою переменную на предмет определенного состояния флага.

Я хочу указать, что моя переменная только любая комбинация :

  • None
  • Student
  • Assistant
  • Demonstration

Поэтому, если она имеет какие-либо другие значения перечисления, переменная не будет удовлетворять критерию.

Сначала я началс этим:

bool bIsPersonnel = true;

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

Но я быстро понял, что существует несколько вариантов выбора.

Есть ли более простой способ?

Я не вижу, как подсказывает, что помогает ответ,Я думаю, что проще всего сделать мой тест в обратном порядке.Просто проверьте, есть ли у него другие флаги , тогда я знаю, что это персонал!

Ответы [ 5 ]

6 голосов
/ 31 марта 2019

Вы можете применить маску с помощью оператора ~ побитового отрицания, чтобы найти все недействительные флаги и проверить, были ли они применены.

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);
2 голосов
/ 31 марта 2019

Я думаю, что это работает как ожидалось:

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
2 голосов
/ 31 марта 2019

(неправильный ответ)

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;
0 голосов
/ 31 марта 2019

Просто создайте маску значений для проверки и and маску со значением, вот как флаги проверяются, независимо от количества флагов

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

Не нужно проверять AssignmentType.Noneпотому что это не сам флаг, а зарезервированное значение, равное 0, используемое для проверки того, что ни один из флагов не установлен.Если комбинация содержит и «нет флага», и «какой-то другой флаг», то это не имеет смысла, верно?Если вам нужно проверить условие «нет флага», то проверьте его отдельно

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));
}
0 голосов
/ 31 марта 2019

На данный момент я решил провести обратный тест:

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

Это проще всего, потому что мы знаем, что если какой-либо из этих флагов установлен, человек будет "Персонал". Другие флаги находятся вне поля зрения, и нам не нужно тестировать конфигурации с несколькими флагами.

...