Testing for bitwise Enum values

I haven't really used bitwise enums before, and I just want to make sure my testing is correct. I am most interested in testing for the values None and All. We receive data from a webservice that utilises this enum to categorise certain pieces of the data. Given that, I am assuming that nether None nor All would ever be combined with any other value.

Given the following bitwise enum definition;

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

I read the following quote on this MSDN site about FlagAttributes;

Use None as the name of the flag нумерованная константа, значение которой нуль. Вы не можете использовать None нумерованная константа в побитовом И операция для проверки флага, потому что результат всегда равен нулю. Однако, вы можете выполнить логический, а не побитовое сравнение между числовое значение и None перечисленные константа, чтобы определить, есть ли какие-либо биты в числовом значении.

Относится ли логическое сравнение в этом случае к обычному тесту на равенство для перечислений? Например:

TrainingComponentTypes tct = TrainingComponentTypes.None; 
if (tct == TrainingComponentTypes.None) 
{ ... }

Для побитового сравнения я выполняю следующее:

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

Наконец, при тестировании для всех я пробовал как логическое, так и побитовое сравнение, и оба они возвращают одно и то же. . Должен ли я использовать здесь один вместо другого? Например;

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

Итак, вкратце, я хотел бы узнать следующее о побитовых перечислениях:

  1. Я понимаю логическое сравнение правильное, учитывая мой пример над?
  2. Так я выступаю побитовое сравнение правильно?
  3. Как правильно обращаться со «Все» значение (побитовое или логическое). Я не уверен, получим ли мы когда-нибудь значение, в котором All было бы объединено с другими типами TrainingComponentTypes. Я не понимаю, зачем нам, но тогда, как знать?
  4. Правильно ли я предполагаю, что переключатель заявлений в принципе не должно быть используется для побитовых перечислений (если нет кажется частным случаем и требует логического сравнения)?

Спасибо, Крис

17
задан Dulini Atapattu 24 May 2011 в 04:36
поделиться

2 ответа

Является ли мое понимание логического сравнения правильным, учитывая мой пример выше?

Да, логический в этом контексте означает операторы равенства и неравенства.

Является ли способ выполнения побитового сравнения правильным?

Да, но есть более простой способ: Enum.HasFlag . Например:

tct.HasFlag(TrainingComponentTypes.Qualification)

вместо:

(tct & TrainingComponentTypes.Qualification) == TrainingComponentTypes.Qualification

Как правильно обрабатывать значение «Все» (побитовое или логическое). Я не уверен, получим ли мы когда-либо значение, в котором All было бы объединено с другими типами TrainingComponentTypes. Я не могу понять, почему мы это сделаем, но тогда, вы никогда не знаете?

Я думаю, что лучше определить All в самом enum как побитовое ИЛИ всех его частей. Но вы увидите, что люди делают это в обоих направлениях.

Прав ли я, если предположить, что операторы switch в основном не должны использоваться для побитовых перечислений (если ни один из них не является особым случаем и требует логического сравнения)?

Нет , не за что. Не стесняйтесь использовать их в switch утверждениях. Значения case должны быть константами, но они могут быть выражениями и проверяться на равенство. Компилятор скажет вам, если вы делаете что-то глупое, например, попробуйте дважды использовать одно и то же значение case.

8
ответ дан 30 November 2019 в 13:03
поделиться

1 и 2 - да, однако есть способ сделать его немного легче для чтения:

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

3 - Я не уверен, что вам вообще нужна вся ценность. Я бы удалил его.

4 - Да, оператор switch обычно не имеет смысла для перечислений Flags.

0
ответ дан 30 November 2019 в 13:03
поделиться
Другие вопросы по тегам:

Похожие вопросы: