Как сохранить несколько состояний в одной переменной?

StackOverflow https://stackoverflow.com/questions/1855211

  •  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;
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top