Как хранить несколько состояний в одной переменной? - PullRequest
3 голосов
/ 06 декабря 2009

Мой объект Item имеет несколько двоичных состояний, которые можно комбинировать

bool CanBeSold;
bool CanBeBought;
bool CanBeExchanged;

Мне нужно сохранить текущую комбинацию значений в одну переменную. Причина в том, что мне нужно хранить это значение в БД. В C ++ я бы создал битовую маску где одно государство занимает немного. Это хорошая практика в .NET?

Ответы [ 4 ]

13 голосов
/ 06 декабря 2009

Вы можете использовать перечисление с атрибутом Flags:

[Flags]
enum MyStates {
  CanBeSold = 1,
  CanBeBought = 2,
  CanBeExchanged = 4
}

Поскольку перечисления являются неотъемлемыми типами данных, вы можете комбинировать их обычным способом:

state = MyStates.CanBeSold | MyStates.CanBeExchanged

Обратите внимание, что это работает только тогда, когда значения перечисления имеют степень двойки (как указано в комментарии Дуг Фергюсон ), поэтому их можно легко комбинировать и не перекрывать их при установке нескольких значений.

Вы также можете определить значения как комбинации нескольких других значений:

 CanBeSoldOrBought = CanBeSold | CanBeBought

или

 CanBeSoldOrBought = 3

, который также работает как ожидалось. Это видно, например, для прав доступа к файлам, где ReadWrite обычно является комбинацией битов чтения и записи.

И да, это довольно распространенная практика. Сам фреймворк также использует его в нескольких местах.

Обычный способ проверить для определенного установленного бита -

if ((state & MyStates.CanBeSold) != 0) { ... }
7 голосов
/ 06 декабря 2009

Создает перечисление, где значения соответствуют битам в целом числе. Добавление атрибута Flags позволило вам выполнить еще несколько битовых операций со значениями перечисления.

[Flags]
public enum CanBe {
  Sold = 1,
  Bought = 2,
  Exchanged = 4
}

Теперь вы можете просто использовать оператор или между значениями:

CanBe can = CabBe.Sold | CanBe.Exchanged.

Вы можете добавить состояние с помощью оператора | =:

can |= CanBe.Sold;

Или несколько состояний:

can |= CanBe.Sold | CanBe.Bought;

Вы можете сохранить состояние с помощью оператора & =:

can &= CanBe.Sold;

Или несколько состояний:

can &= CanBe.Sold | CanBe.Bought;

Вы можете удалить состояния, используя оператор ~ для создания дополнения к значению:

can &= ~CabBe.Bough;

Или несколько состояний:

can &= ~(CabBe.Bough | CanBe.Exchanged);

Вы можете проверить состояние с помощью оператора &:

if ((can & CanBe.Sold) != 0) ...

или несколько состояний одновременно:

if ((can & (CanBe.Sold | CanBe.Bought)) != 0) ...

Или убедитесь, что установлено несколько состояний:

if ((can & (CanBe.Sold | CanBe.Bought)) == (CanBe.Sold | CanBe.Bought)) ...
2 голосов
/ 06 декабря 2009

Вы можете использовать перечисление Flags с каждым указанным битом

[Flags]
enum MyStates {
    CanBeSold = 0x1,
    CanBeBought = 0x2,
    CanBeExchanged = 0x4,
}

MyStates m_Flags;

// to set a flag:
m_Flags |= MyStates.CanBeSold;

// to unset a flag:
m_Flags &= ~MyStates.CanBeSold;
2 голосов
/ 06 декабря 2009

Вы можете сделать это с помощью битовых масок в .NET.

В вашем перечислении вы можете определить свои состояния как значения

public enum ItemState { CanBeSold = 1; CanBeBought = 2; CanBeExchanged = 4 }

Тогда внутри вашего объекта вы можете сделать

if (item.State ^ ItemState.CanBeSold) ....
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...