218

For the life of me, I can't remember how to set, delete, toggle or test a bit in a bitfield. Either I'm unsure or I mix them up because I rarely need these. So a "bit-cheat-sheet" would be nice to have.

For example:

flags = flags | FlagsEnum.Bit4;  // Set bit 4.

or

if ((flags & FlagsEnum.Bit4)) == FlagsEnum.Bit4) // Is there a less verbose way?

Can you give examples of all the other common operations, preferably in C# syntax using a [Flags] enum?

Drew Noakes
  • 300,895
  • 165
  • 679
  • 742
steffenj
  • 7,967
  • 10
  • 35
  • 41
  • I'm not aware of a less verbose way to do the bit test – Andy Johnson May 17 '11 at 15:37
  • 2
    @Andy, there's an API for the bit test in .NET 4 now. – Drew Noakes May 30 '11 at 17:48
  • @Drew Interesting. Could you provide a link? I'm not using 4 yet, but I'd like to find out more. – Andy Johnson May 31 '11 at 09:52
  • @Andy, see [my answer below](http://stackoverflow.com/questions/93744/most-common-c-bitwise-operations/6179308#6179308). – Drew Noakes Jun 03 '11 at 10:48
  • 5
    This has been answered before [here](http://stackoverflow.com/questions/47981/how-do-you-set-clear-and-toggle-a-single-bit-in-c) – Greg Rogers Sep 18 '08 at 15:48
  • 9
    too bad that link doesn't appear in the question hints for this topic. – cori Sep 18 '08 at 15:52
  • 12
    That question is tagged for c/c++, though, so someone searching for info about C# would probably not look there even though the syntax appears to be the same. – Adam Lassek Sep 18 '08 at 16:11
  • @GregRogers: That answer is a useful link, but it isn't directly applicable to enum flags. Specifically, it shows BIT-SHIFTING, which isn't needed here. This question is worthwhile - and would be even better if any of the answers below had that simple list of the 4 common operations, but without the bit-shifting :) – ToolmakerSteve Mar 18 '14 at 23:21
  • FYI, Re bit test, if in a pre-4 version (so `HasFlag` doesn't exist) and you know you are testing a single bit, could replace `== FlagsEnum.Bit4` with `!= 0`. HOWEVER, it may be better to stick with the original idiom because it also works for enum tests involving multiple bits. E.g. given `None = 0`, `Read = 1`, `Write = 2`, `ReadWrite = Read + Write`, the original idiom also works for `ReadWrite`, whereas `(flags & FlagsEnum.ReadWrite) != 0` sometimes won't give the desired answer; e.g. if only Read bit is set the answer should be `False`, but will be `True`. – ToolmakerSteve Mar 18 '14 at 23:31

11 Answers11

297

I did some more work on these extensions - You can find the code here

I wrote some extension methods that extend System.Enum that I use often... I'm not claiming that they are bulletproof, but they have helped... Comments removed...

namespace Enum.Extensions {

    public static class EnumerationExtensions {

        public static bool Has<T>(this System.Enum type, T value) {
            try {
                return (((int)(object)type & (int)(object)value) == (int)(object)value);
            } 
            catch {
                return false;
            }
        }

        public static bool Is<T>(this System.Enum type, T value) {
            try {
                return (int)(object)type == (int)(object)value;
            }
            catch {
                return false;
            }    
        }


        public static T Add<T>(this System.Enum type, T value) {
            try {
                return (T)(object)(((int)(object)type | (int)(object)value));
            }
            catch(Exception ex) {
                throw new ArgumentException(
                    string.Format(
                        "Could not append value from enumerated type '{0}'.",
                        typeof(T).Name
                        ), ex);
            }    
        }


        public static T Remove<T>(this System.Enum type, T value) {
            try {
                return (T)(object)(((int)(object)type & ~(int)(object)value));
            }
            catch (Exception ex) {
                throw new ArgumentException(
                    string.Format(
                        "Could not remove value from enumerated type '{0}'.",
                        typeof(T).Name
                        ), ex);
            }  
        }

    }
}

Then they are used like the following

SomeType value = SomeType.Grapes;
bool isGrapes = value.Is(SomeType.Grapes); //true
bool hasGrapes = value.Has(SomeType.Grapes); //true

value = value.Add(SomeType.Oranges);
value = value.Add(SomeType.Apples);
value = value.Remove(SomeType.Grapes);

bool hasOranges = value.Has(SomeType.Oranges); //true
bool isApples = value.Is(SomeType.Apples); //false
bool hasGrapes = value.Has(SomeType.Grapes); //false
GmodCake
  • 427
  • 3
  • 11
  • 24
hugoware
  • 35,731
  • 24
  • 60
  • 70
  • 1
    I also found this useful - Any ideas how I can modify it so it works on any underlying type? – Charlie Salts Feb 14 '10 at 05:10
  • 8
    These extensions just made my day, my week, my month, and quite possibly my year. – thaBadDawg Mar 03 '10 at 22:39
  • Thank you! Everybody: be sure to check out the update Hugoware has linked to. – Helge Klein Mar 30 '11 at 20:12
  • A very nice set of extensions. It's a shame they require boxing, though I can't think of an alternative that doesn't use boxing and is this succinct. Even the new `HasFlag` method on `Enum` requires boxing. – Drew Noakes May 30 '11 at 17:52
  • 5
    @Drew: See http://code.google.com/p/unconstrained-melody for a way of avoiding boxing :) – Jon Skeet Sep 19 '11 at 21:56
  • Greats! thanks!. I'm failing to use this code inside another T function like function Some(T initial) where T : struct { ... if (EnumerationExtensions.Has(inicial, someTvalue)) { do something} } .... the compiler says "Error CS1503: Argument `#1' cannot convert `T' expression to type `System.Enum' (CS1503)" any idea? – rolivares Jun 06 '13 at 10:44
  • Nice, I was about to write this for myself, but found this instead. I added a method called `Set(T value, bool turnItOn)` for my laziness :) – T.Coutlakis Oct 19 '13 at 20:53
  • It does not seem to support enums with more bits than 32, right? It casts to int, and that one only has 32 bits. =3 – Ray May 08 '15 at 15:36
118

In .NET 4 you can now write:

flags.HasFlag(FlagsEnum.Bit4)
Drew Noakes
  • 300,895
  • 165
  • 679
  • 742
  • 4
    +1 for pointing that out, although `FlagsEnum` is an ugly name. :) – Joseph Yaduvanshi Jul 19 '11 at 14:25
  • 5
    @Jim, perhaps. It's just a sample name, as used in the original question, so you're free to change it in your code. – Drew Noakes Jul 20 '11 at 07:46
  • 15
    I know! But ugly names are like IE6 and will probably never go away :( – Joseph Yaduvanshi Jul 20 '11 at 20:18
  • 5
    @JimSchubert, again, I just reproduced the type name from the original question so as not to confuse the issue. The [.NET Enumeration Type Naming Guidelines](http://msdn.microsoft.com/en-us/library/4x252001(v=vs.71).aspx) indicate that all `[Flags]` enums should have pluralised names, so the name `FlagsEnum` has even more serious issues than ugliness. – Drew Noakes Jan 16 '13 at 11:48
  • 1
    I also recommend [Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries](http://www.amazon.com/Framework-Design-Guidelines-Conventions-Libraries/dp/0321545613). It is a little expensive to buy, but I believe Safari Online and Books24x7 both offer it for subscribers. – Joseph Yaduvanshi Jan 16 '13 at 14:34
  • 1
    @JimSchubert - Please note that ... sadly ... you were right; some of our older software *still* uses IE6. Oh! The shame of it! – Paul Oct 03 '22 at 09:49
98

The idiom is to use the bitwise or-equal operator to set bits:

flags |= 0x04;

To clear a bit, the idiom is to use bitwise and with negation:

flags &= ~0x04;

Sometimes you have an offset that identifies your bit, and then the idiom is to use these combined with left-shift:

flags |= 1 << offset;
flags &= ~(1 << offset);
Stephen Deken
  • 3,665
  • 26
  • 31
22

@Drew

Note that except in the simplest of cases, the Enum.HasFlag carries a heavy performance penalty in comparison to writing out the code manually. Consider the following code:

[Flags]
public enum TestFlags
{
    One = 1,
    Two = 2,
    Three = 4,
    Four = 8,
    Five = 16,
    Six = 32,
    Seven = 64,
    Eight = 128,
    Nine = 256,
    Ten = 512
}


class Program
{
    static void Main(string[] args)
    {
        TestFlags f = TestFlags.Five; /* or any other enum */
        bool result = false;

        Stopwatch s = Stopwatch.StartNew();
        for (int i = 0; i < 10000000; i++)
        {
            result |= f.HasFlag(TestFlags.Three);
        }
        s.Stop();
        Console.WriteLine(s.ElapsedMilliseconds); // *4793 ms*

        s.Restart();
        for (int i = 0; i < 10000000; i++)
        {
            result |= (f & TestFlags.Three) != 0;
        }
        s.Stop();
        Console.WriteLine(s.ElapsedMilliseconds); // *27 ms*        

        Console.ReadLine();
    }
}

Over 10 million iterations, the HasFlags extension method takes a whopping 4793 ms, compared to the 27 ms for the standard bitwise implementation.

Chuck Dee
  • 690
  • 1
  • 19
  • 29
  • 10
    Whilst certainly interesting and good to point out. You do need to consider the usage. According to this if you aren't performing a couple hundred thousand or more ops you probably aren't even going to notice this. – Joshua Hayes Oct 27 '11 at 12:28
  • 7
    The `HasFlag` method involves boxing/unboxing, which accounts for this difference. But the cost is so trivial (0.4µs) that unless you're in a tight loop, I would take the more readable (and less likely buggy) declarative API call any day. – Drew Noakes Oct 15 '12 at 23:57
  • 9
    Depending on usage, it could be an issue. And since I work with loaders quite a bit, I figured it was good to point out. – Chuck Dee Oct 25 '12 at 21:56
  • why it can't be just `result = f.HasFlag(TestFlags.Three)` – Beingnin May 17 '22 at 04:07
  • If you need to care how performant HasFlag is, then it's likely that your application suffers from far greater problems and optimizing enum usages will only provide a temporary solution at best. Your time will be better spent figuring out how to replace enums with the concepts of OOP. – Ryan Naccarato Feb 08 '23 at 15:50
  • @RyanNaccarato - thanks for this reply to an 11 year old post just to be condescending. Enums are tools and should be used as such, and do not necessarily mean that OOP concepts are not being applied correctly. – Chuck Dee Feb 09 '23 at 16:13
  • @ChuckDee I apologize if my comment came across as condescending, I meant it to help young developers avoid this very common coding trap. As for enums being tools, I agree. The only problem is that they're never used for anything other than a developer attempting to get around OOP. After working for a number of companies. small, large, and very large, I have literally never seen an enum used correctly. If fact, they're always the root cause of an application being impossible to work on, constantly plagued by bugs, and eventually worthless. – Ryan Naccarato Feb 10 '23 at 17:04
17

.NET's built-in flag enum operations are unfortunately quite limited. Most of the time users are left with figuring out the bitwise operation logic.

In .NET 4, the method HasFlag was added to Enum which helps simplify user's code but unfortunately there are many problems with it.

  1. HasFlag is not type-safe as it accepts any type of enum value argument, not just the given enum type.
  2. HasFlag is ambiguous as to whether it checks if the value has all or any of the flags provided by the enum value argument. It's all by the way.
  3. HasFlag is rather slow as it requires boxing which causes allocations and thus more garbage collections.

Due in part to .NET's limited support for flag enums I wrote the OSS library Enums.NET which addresses each of these issues and makes dealing with flag enums much easier.

Below are some of the operations it provides along with their equivalent implementations using just the .NET framework.

Combine Flags

.NET             flags | otherFlags

Enums.NET flags.CombineFlags(otherFlags)


Remove Flags

.NET             flags & ~otherFlags

Enums.NET flags.RemoveFlags(otherFlags)


Common Flags

.NET             flags & otherFlags

Enums.NET flags.CommonFlags(otherFlags)


Toggle Flags

.NET             flags ^ otherFlags

Enums.NET flags.ToggleFlags(otherFlags)


Has All Flags

.NET             (flags & otherFlags) == otherFlags or flags.HasFlag(otherFlags)

Enums.NET flags.HasAllFlags(otherFlags)


Has Any Flags

.NET             (flags & otherFlags) != 0

Enums.NET flags.HasAnyFlags(otherFlags)


Get Flags

.NET

Enumerable.Range(0, 64)
  .Where(bit => ((flags.GetTypeCode() == TypeCode.UInt64 ? (long)(ulong)flags : Convert.ToInt64(flags)) & (1L << bit)) != 0)
  .Select(bit => Enum.ToObject(flags.GetType(), 1L << bit))`

Enums.NET flags.GetFlags()


I'm trying to get these improvements incorporated into .NET Core and maybe eventually the full .NET Framework. You can check out my proposal here.

TylerBrinkley
  • 1,066
  • 10
  • 16
7

C++ syntax, assuming bit 0 is LSB, assuming flags is unsigned long:

Check if Set:

flags & (1UL << (bit to test# - 1))

Check if not set:

invert test !(flag & (...))

Set:

flag |= (1UL << (bit to set# - 1))

Clear:

flag &= ~(1UL << (bit to clear# - 1))

Toggle:

flag ^= (1UL << (bit to set# - 1))
Anya Shenanigans
  • 91,618
  • 3
  • 107
  • 122
6

For the best performance and zero garbage, use this:

using System;
using T = MyNamespace.MyFlags;

namespace MyNamespace
{
    [Flags]
    public enum MyFlags
    {
        None = 0,
        Flag1 = 1,
        Flag2 = 2
    }

    static class MyFlagsEx
    {
        public static bool Has(this T type, T value)
        {
            return (type & value) == value;
        }

        public static bool Is(this T type, T value)
        {
            return type == value;
        }

        public static T Add(this T type, T value)
        {
            return type | value;
        }

        public static T Remove(this T type, T value)
        {
            return type & ~value;
        }
    }
}
Mark Bamford
  • 113
  • 1
  • 5
  • I like this short & clean approach, but wouldn't it be better/clearer if the Add and Remove methods would change the original? – LukasKroess May 13 '21 at 18:56
  • Since enum is a value type, this would not be possible without a ref parameter, which wouldn't work as an extension method. – Mark Bamford May 20 '21 at 13:58
4

Bitwise (Flags) enum guide

Old, but wanted to take a stab at a cheat sheet, even if for my own reference:

Operation Syntax Example
On |= e |= E.A
Off &= + ~ e &= ~E.A
Toggle ^= e ^= E.A
Test (.NET API) .HasFlag e.HasFlag(E.A)
Test (bitwise) (see example) (e & E.A) == E.A

Examples

[Flags]
enum E {
    A = 0b1,
    B = 0b10,
    C = 0b100
}

E e = E.A;        // Assign (e = A)
e |= E.B | E.C;   // Add    (e = A, B, C)
e &= ~E.A & ~E.B; // Remove (e = C) -- alt syntax: &= ~(E.A | E.B)
e ^= E.A | E.C;   // Toggle (e = A)
e.HasFlag(E.A);   // Test   (returns true)

// Testing multiple flags using bit operations:
bool hasAandB = ( e & (E.A | E.B) ) == (E.A | E.B);

Bonus: defining a Flags enum

Typically, we use integers like so:

[Flags]
enum E {
    A = 1,
    B = 2,
    C = 4,
    // etc.

But as we approach larger numbers, it's not as easy to calculate the next value:

  // ...
  W = 4194304,
  X = 8388608,
  // ..

There are a couple of alternatives, however: binary and hexadecimal literals.

For Binary, just append a 0 at the end of the previous value:

[Flags]
enum E {
    A = 0b1,
    B = 0b10,
    C = 0b100,
    // ...
    W = 0b100_0000_0000_0000_0000_0000,
    X = 0b1000_0000_0000_0000_0000_0000,

Hexadecimal also has a handy pattern and might look a bit less ugly: cycle through 1, 2, 4, 8, adding a zero after each complete iteration.

[Flags]
enum E {
    A = 0x1,
    B = 0x2,
    C = 0x4,
    D = 0x8,
    E = 0x10, // 16
    F = 0x20, // 32, etc.
    // ...
    W = 0x400000,
    X = 0x800000,
Connor Low
  • 5,900
  • 3
  • 31
  • 52
2

To test a bit you would do the following: (assuming flags is a 32 bit number)

Test Bit:

if((flags & 0x08) == 0x08)
(If bit 4 is set then its true) Toggle Back (1 - 0 or 0 - 1):
flags = flags ^ 0x08;
Reset Bit 4 to Zero:
flags = flags & 0xFFFFFF7F;
Andy Johnson
  • 7,938
  • 4
  • 33
  • 50
Nashirak
  • 71
  • 4
  • 3
    -1 since this does not even bother with enums? Plus, hand-coding the values is fragile... I would at least write `~0x08` instead of `0xFFFFFFF7`... (the actual mask for 0x8) – Ben Mosher Jun 21 '12 at 15:22
  • 2
    At first I was thinking that Ben's -1 was harsh, but the use of "0xFFFFFF7F" does make this an especially poor example. – ToolmakerSteve Mar 18 '14 at 23:25
2

This was inspired by using Sets as indexers in Delphi, way back when:

/// Example of using a Boolean indexed property
/// to manipulate a [Flags] enum:

public class BindingFlagsIndexer
{
  BindingFlags flags = BindingFlags.Default;

  public BindingFlagsIndexer()
  {
  }

  public BindingFlagsIndexer( BindingFlags value )
  {
     this.flags = value;
  }

  public bool this[BindingFlags index]
  {
    get
    {
      return (this.flags & index) == index;
    }
    set( bool value )
    {
      if( value )
        this.flags |= index;
      else
        this.flags &= ~index;
    }
  }

  public BindingFlags Value 
  {
    get
    { 
      return flags;
    } 
    set( BindingFlags value ) 
    {
      this.flags = value;
    }
  }

  public static implicit operator BindingFlags( BindingFlagsIndexer src )
  {
     return src != null ? src.Value : BindingFlags.Default;
  }

  public static implicit operator BindingFlagsIndexer( BindingFlags src )
  {
     return new BindingFlagsIndexer( src );
  }

}

public static class Class1
{
  public static void Example()
  {
    BindingFlagsIndexer myFlags = new BindingFlagsIndexer();

    // Sets the flag(s) passed as the indexer:

    myFlags[BindingFlags.ExactBinding] = true;

    // Indexer can specify multiple flags at once:

    myFlags[BindingFlags.Instance | BindingFlags.Static] = true;

    // Get boolean indicating if specified flag(s) are set:

    bool flatten = myFlags[BindingFlags.FlattenHierarchy];

    // use | to test if multiple flags are set:

    bool isProtected = ! myFlags[BindingFlags.Public | BindingFlags.NonPublic];

  }
}
1

C++ operations are: & | ^ ~ (for and, or, xor and not bitwise operations). Also of interest are >> and <<, which are bitshift operations.

So, to test for a bit being set in a flag, you would use: if (flags & 8) //tests bit 4 has been set

workmad3
  • 25,101
  • 4
  • 35
  • 56