Как сохранить несколько состояний в одной переменной?
-
13-09-2019 - |
Вопрос
Мой объект Item
имеет несколько двоичных состояний, которые можно комбинировать
bool CanBeSold;
bool CanBeBought;
bool CanBeExchanged;
Мне нужно сохранить текущую комбинацию значений в одну переменную.Причина в том, что мне нужно сохранить это значение в БД.В C ++ я бы создал немного маски, где одно государство занимает немного.Это хорошая практика в .NET?
Решение
Вы можете использовать перечисление с помощью 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) { ... }
Другие советы
Создайте перечисление, значения которого соответствуют битам целого числа.Добавление атрибута 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)) ...
Вы также можете сделать это с помощью битовых масок и в .NET.
Внутри вашего перечисления вы можете определить свои состояния как значения.
public enum ItemState { CanBeSold = 1; CanBeBought = 2; CanBeExchanged = 4 }
Затем внутри вашего объекта вы можете сделать
if (item.State ^ ItemState.CanBeSold) ....
Вы можете использовать перечисление 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;