By steffenj


2008-09-18 15:46:20 8 Comments

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?

10 comments

@Mark Bamford 2019-03-03 20:19:52

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;
        }
    }
}

@TylerBrinkley 2017-06-14 17:27:58

.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.

@Hugoware 2009-01-06 16:31:05

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

@Charlie Salts 2010-02-14 05:10:40

I also found this useful - Any ideas how I can modify it so it works on any underlying type?

@thaBadDawg 2010-03-03 22:39:04

These extensions just made my day, my week, my month, and quite possibly my year.

@Helge Klein 2011-03-30 20:12:46

Thank you! Everybody: be sure to check out the update Hugoware has linked to.

@Drew Noakes 2011-05-30 17:52:21

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.

@Jon Skeet 2011-09-19 21:56:38

@Drew: See code.google.com/p/unconstrained-melody for a way of avoiding boxing :)

@rolivares 2013-06-06 10:44:09

Greats! thanks!. I'm failing to use this code inside another T function like function Some<T>(T initial) where T : struct { ... if (EnumerationExtensions.Has<T>(inicial, someTvalue)) { do something} } .... the compiler says "Error CS1503: Argument #1' cannot convert T' expression to type `System.Enum' (CS1503)" any idea?

@T.Coutlakis 2013-10-19 20:53:54

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 :)

@Ray 2015-05-08 15:36:29

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

@Tony Tanzillo 2012-03-09 22:09:36

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];

  }
}

@amuliar 2013-11-20 12:41:42

This even does not compile if BindingFlags is byte enum: this.flags &= ~index;

@Chuck Dee 2011-08-24 19:51:30

@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.

@Joshua Hayes 2011-10-27 12:28:30

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.

@Drew Noakes 2012-10-15 23:57:15

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.

@Chuck Dee 2012-10-25 21:56:35

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.

@Drew Noakes 2011-05-30 17:48:11

In .NET 4 you can now write:

flags.HasFlag(FlagsEnum.Bit4)

@Jim Schubert 2011-07-19 14:25:49

+1 for pointing that out, although FlagsEnum is an ugly name. :)

@Drew Noakes 2011-07-20 07:46:11

@Jim, perhaps. It's just a sample name, as used in the original question, so you're free to change it in your code.

@Jim Schubert 2011-07-20 20:18:52

I know! But ugly names are like IE6 and will probably never go away :(

@Drew Noakes 2013-01-16 11:48:22

@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 indicate that all [Flags] enums should have pluralised names, so the name FlagsEnum has even more serious issues than ugliness.

@Jim Schubert 2013-01-16 14:34:08

I also recommend Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries. It is a little expensive to buy, but I believe Safari Online and Books24x7 both offer it for subscribers.

@Nashirak 2008-09-18 16:00:01

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;

@Ben Mosher 2012-06-21 15:22:50

-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)

@ToolmakerSteve 2014-03-18 23:25:23

At first I was thinking that Ben's -1 was harsh, but the use of "0xFFFFFF7F" does make this an especially poor example.

@Petesh 2008-09-18 15:57:25

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))

@Stephen Deken 2008-09-18 15:50:16

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);

@workmad3 2008-09-18 15:50:04

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

@Andy Johnson 2011-05-17 15:38:54

Question relates to c#, not c++

@ToolmakerSteve 2014-03-18 23:18:52

On the other hand, C# uses the same operators: msdn.microsoft.com/en-us/library/6a71f45d.aspx

@pqsk 2015-03-13 15:57:50

In defense of @workmad3, the original tags had C and C++

Related Questions

Sponsored Content

27 Answered Questions

[SOLVED] How to cast int to enum?

  • 2008-08-27 03:58:21
  • lomaxx
  • 1306208 View
  • 3074 Score
  • 27 Answer
  • Tags:   c# enums casting int

9 Answered Questions

27 Answered Questions

[SOLVED] How to get an enum value from a string value in Java?

  • 2009-03-02 22:56:34
  • Malachi
  • 1079849 View
  • 1920 Score
  • 27 Answer
  • Tags:   java enums

29 Answered Questions

[SOLVED] How to enumerate an enum

27 Answered Questions

[SOLVED] Get int value from enum in C#

  • 2009-06-03 06:46:39
  • jim
  • 1448130 View
  • 1737 Score
  • 27 Answer
  • Tags:   c# enums casting int

66 Answered Questions

[SOLVED] What is the difference between String and string in C#?

14 Answered Questions

[SOLVED] Comparing Java enum members: == or equals()?

  • 2009-11-17 17:26:27
  • Matt Ball
  • 633675 View
  • 1668 Score
  • 14 Answer
  • Tags:   java enums

11 Answered Questions

[SOLVED] What does the [Flags] Enum Attribute mean in C#?

  • 2008-08-12 04:09:16
  • Brian Leahy
  • 464421 View
  • 1401 Score
  • 11 Answer
  • Tags:   c# enums flags

Sponsored Content