My object Item
has several binary states which can be combined
bool CanBeSold;
bool CanBeBought;
bool CanBeExchang开发者_如何学运维ed;
I need to store current combination of values into one variable. The reason is that I need to store this value in DB. In C++ I would create a bit-mask where one state occupies some bit. Is it good practice in .NET?
You can use an enumeration with the Flags
attribute:
[Flags]
enum MyStates {
CanBeSold = 1,
CanBeBought = 2,
CanBeExchanged = 4
}
Since enumerations are integral data types underneath you can combine them in the usual fashion:
state = MyStates.CanBeSold | MyStates.CanBeExchanged
Note that this only works when the enum values are powers of two (as Doug Ferguson pointed out in a comment), so they can be combined easily and don't overlap when multiple ones are set.
You can also define values as combinations of multiple other values:
CanBeSoldOrBought = CanBeSold | CanBeBought
or
CanBeSoldOrBought = 3
which then also works as expected. This can be seen for example for file permissions where ReadWrite usually is a combination of the Read and Write bits.
And yes, that's quite a common practice. The framework itself also uses it in several places.
The usual way to check for a particular bit being set is then
if ((state & MyStates.CanBeSold) != 0) { ... }
Create an enum where the values correspond to bits in an integer. Adding the Flags attribute enabled you to do some more bit operations on the enum values.
[Flags]
public enum CanBe {
Sold = 1,
Bought = 2,
Exchanged = 4
}
Now you can just use the or operator between the values:
CanBe can = CabBe.Sold | CanBe.Exchanged.
You can add a state with the |= operator:
can |= CanBe.Sold;
Or several states:
can |= CanBe.Sold | CanBe.Bought;
You can keep a state with the &= operator:
can &= CanBe.Sold;
Or several states:
can &= CanBe.Sold | CanBe.Bought;
You can remove states by using the ~ operator to create a complement to a value:
can &= ~CabBe.Bough;
Or seveal states:
can &= ~(CabBe.Bough | CanBe.Exchanged);
You can check for a state using the & operator:
if ((can & CanBe.Sold) != 0) ...
Or several states at once:
if ((can & (CanBe.Sold | CanBe.Bought)) != 0) ...
Or check that several states are all set:
if ((can & (CanBe.Sold | CanBe.Bought)) == (CanBe.Sold | CanBe.Bought)) ...
You can do this with bit masks in .NET too.
Within your enum you can define your states as values
public enum ItemState { CanBeSold = 1; CanBeBought = 2; CanBeExchanged = 4 }
Then within your object, you can do
if (item.State ^ ItemState.CanBeSold) ....
You can use a Flags enum with each bit specified
[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;
精彩评论