Why use flags+bitmasks rather than a series of booleans?

12,551

Solution 1

It was traditionally a way of reducing memory usage. So, yes, its quite obsolete in C# :-)

As a programming technique, it may be obsolete in today's systems, and you'd be quite alright to use an array of bools, but...

It is fast to compare values stored as a bitmask. Use the AND and OR logic operators and compare the resulting 2 ints.

It uses considerably less memory. Putting all 4 of your example values in a bitmask would use half a byte. Using an array of bools, most likely would use a few bytes for the array object plus a long word for each bool. If you have to store a million values, you'll see exactly why a bitmask version is superior.

It is easier to manage, you only have to deal with a single integer value, whereas an array of bools would store quite differently in, say a database.

And, because of the memory layout, much faster in every aspect than an array. It's nearly as fast as using a single 32-bit integer. We all know that is as fast as you can get for operations on data.

Solution 2

  • Easy setting multiple flags in any order.

  • Easy to save and get a serie of 0101011 to the database.

Solution 3

Among other things, its easier to add new bit meanings to a bitfield than to add new boolean values to a class. Its also easier to copy a bitfield from one instance to another than a series of booleans.

Solution 4

It can also make Methods clearer. Imagine a Method with 10 bools vs. 1 Bitmask.

Solution 5

From a domain Model perspective, it just models reality better in some situations. If you have three booleans like AccountIsInDefault and IsPreferredCustomer and RequiresSalesTaxState, then it doesnn't make sense to add them to a single Flags decorated enumeration, cause they are not three distinct values for the same domain model element.

But if you have a set of booleans like:

 [Flags] enum AccountStatus {AccountIsInDefault=1, 
         AccountOverdue=2 and AccountFrozen=4}

or

  [Flags] enum CargoState {ExceedsWeightLimit=1,  
         ContainsDangerousCargo=2, IsFlammableCargo=4, 
         ContainsRadioactive=8}

Then it is useful to be able to store the total state of the Account, (or the cargo) in ONE variable... that represents ONE Domain Element whose value can represent any possible combination of states.

Share:
12,551
Winston Fassett
Author by

Winston Fassett

Updated on August 25, 2022

Comments

  • Winston Fassett
    Winston Fassett almost 2 years

    Given a case where I have an object that may be in one or more true/false states, I've always been a little fuzzy on why programmers frequently use flags+bitmasks instead of just using several boolean values.

    It's all over the .NET framework. Not sure if this is the best example, but the .NET framework has the following:

    public enum AnchorStyles
    {
        None = 0,
        Top = 1,
        Bottom = 2,
        Left = 4,
        Right = 8
    }
    

    So given an anchor style, we can use bitmasks to figure out which of the states are selected. However, it seems like you could accomplish the same thing with an AnchorStyle class/struct with bool properties defined for each possible value, or an array of individual enum values.

    Of course the main reason for my question is that I'm wondering if I should follow a similar practice with my own code.

    So, why use this approach?

    • Less memory consumption? (it doesn't seem like it would consume less than an array/struct of bools)
    • Better stack/heap performance than a struct or array?
    • Faster compare operations? Faster value addition/removal?
    • More convenient for the developer who wrote it?
  • Winston Fassett
    Winston Fassett almost 15 years
    That's a pretty high-level answer. Can you be specific about what operations are faster/more efficient and why? Or link to an article that justifies your claim?
  • Winston Fassett
    Winston Fassett almost 15 years
    It seems to me that adding boolean values to a class is as easy as: bool newState; Regarding copying, it seems just as easy to copy a struct.
  • ChaosPandion
    ChaosPandion almost 15 years
    Do I really need to give you proof that working with native types and simple logic expressions is fast and efficient?
  • Dykam
    Dykam almost 15 years
    There are 256 combinations, but only 8 flags. Don't confuse them.
  • peterchen
    peterchen almost 15 years
    @Winston: Serialization format changes, and good serializers that accept default values for old data, and where old versions do not throw away unknown fields are hard to find. The binary interface changes, which may cause a chain of required updates, and requires full verisoning support for the structure. (of course the contract would have to state explicitely "unknown bits are ignored" or "unknown bits cause an error"). Also, on implementation level, handling them as a whole IS easier.
  • David Basarab
    David Basarab almost 15 years
    @Winston what if you have created an API? Then everybody that might upgrade to your new version would have to change there code because a new bool was added to a method. While if it was an enum then no changes on there end must be made to keep there same code using it. Which is why the .NET framework favors enums over booleans.
  • Winston Fassett
    Winston Fassett almost 15 years
    @David - I wasn't talking about adding arguments to methods, but rather adding bool fields to structs, which wouldn't affect any calling methods, but to @Peter's point, would affect serialization.
  • Sam Harwell
    Sam Harwell almost 15 years
    Don't forget the order of operations. You have to put parenthesis around the bitwise operation there.
  • ChaosPandion
    ChaosPandion almost 15 years
    Nice catch I am used to Visual Studio having my back.
  • gbjbaanb
    gbjbaanb almost 15 years
    Raymond is talking about bitfields, not bitmasks.
  • AaronLS
    AaronLS over 11 years
    Note that even as seperate columns, SQL Server will optimize these into a single byte: msdn.microsoft.com/en-us/library/ms177603.aspx
  • CoperNick
    CoperNick over 10 years
    256 combinations using bool? It is 8 bool values. 8 bool values is not 256 bytes.
  • user2864740
    user2864740 over 9 years
    -1 No justification is given for "speed and efficiency" and in this case I suspect that it is neither. Consider the counter-style/proposal of: if (AnchorsTop) { .. }.
  • user2864740
    user2864740 over 9 years
    1. Space efficiency only applies in very dense-packing or extremely limited environments; 2. Time efficiency depends on efficient use of the mask (and it is surely not faster to mask-and-compare a single bit than it is to compare a single boolean value); 3. Not applicable, using a boolean type incorrectly is using a boolean type incorrectly.
  • user2864740
    user2864740 over 9 years
    Adding a new field to a C# struct/class is not a breaking change (excepting that previous code is unaware of it). In both cases existing code must be updated to be aware of how to use the new flag.