如何在一个变量中存储多个状态?

Cap*_*mic 3 c# design-patterns bitmask

我的对象Item有几个可以组合的二进制状态

bool CanBeSold;
bool CanBeBought;
bool CanBeExchanged;
Run Code Online (Sandbox Code Playgroud)

我需要将当前的值组合存储到一个变量中.原因是我需要将此值存储在DB中.在C++中,我会创建一个位掩码,其中一个状态占用一些位.这是.NET中的好习惯吗?

Joe*_*oey 13

您可以使用具有以下Flags属性的枚举:

[Flags]
enum MyStates {
  CanBeSold = 1,
  CanBeBought = 2,
  CanBeExchanged = 4
}
Run Code Online (Sandbox Code Playgroud)

由于枚举是下面的整数数据类型,因此您可以通常的方式将它们组合在一起:

state = MyStates.CanBeSold | MyStates.CanBeExchanged
Run Code Online (Sandbox Code Playgroud)

请注意,这只适用于枚举值为2的幂(如Doug Ferguson在注释中指出的那样),因此它们可以轻松组合,并且在设置多个时不会重叠.

您还可以将值定义为多个其他值的组合:

 CanBeSoldOrBought = CanBeSold | CanBeBought
Run Code Online (Sandbox Code Playgroud)

要么

 CanBeSoldOrBought = 3
Run Code Online (Sandbox Code Playgroud)

然后也按预期工作.例如,对于文件权限,可以看到这一点,其中ReadWrite通常是读和写位的组合.

是的,这是一种非常普遍的做法.框架本身也在几个地方使用它.

然后检查特定位的常用方法是

if ((state & MyStates.CanBeSold) != 0) { ... }
Run Code Online (Sandbox Code Playgroud)

  • @Captain Comic:这表明合并这些值是合理的.它还会更改解析和格式化行为. (4认同)
  • 枚举值应为2的幂(如答案中所示),以便它们不重叠. (2认同)

Guf*_*ffa 7

创建一个枚举,其中值对应于整数中的位.添加Flags属性使您可以对枚举值执行更多位操作.

[Flags]
public enum CanBe {
  Sold = 1,
  Bought = 2,
  Exchanged = 4
}
Run Code Online (Sandbox Code Playgroud)

现在你可以在值之间使用or运算符:

CanBe can = CabBe.Sold | CanBe.Exchanged.
Run Code Online (Sandbox Code Playgroud)

您可以使用| =运算符添加状态:

can |= CanBe.Sold;
Run Code Online (Sandbox Code Playgroud)

或者几个州:

can |= CanBe.Sold | CanBe.Bought;
Run Code Online (Sandbox Code Playgroud)

您可以使用&=运算符保持状态:

can &= CanBe.Sold;
Run Code Online (Sandbox Code Playgroud)

或者几个州:

can &= CanBe.Sold | CanBe.Bought;
Run Code Online (Sandbox Code Playgroud)

您可以使用〜运算符删除状态来创建值的补码:

can &= ~CabBe.Bough;
Run Code Online (Sandbox Code Playgroud)

或者seveal状态:

can &= ~(CabBe.Bough | CanBe.Exchanged);
Run Code Online (Sandbox Code Playgroud)

您可以使用&运算符检查状态:

if ((can & CanBe.Sold) != 0) ...
Run Code Online (Sandbox Code Playgroud)

或者几个州立刻:

if ((can & (CanBe.Sold | CanBe.Bought)) != 0) ...
Run Code Online (Sandbox Code Playgroud)

或者检查几个状态是否全部设置:

if ((can & (CanBe.Sold | CanBe.Bought)) == (CanBe.Sold | CanBe.Bought)) ...
Run Code Online (Sandbox Code Playgroud)