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?
The idiom is to use the bitwise or-equal operator to set bits:
To clear a bit, the idiom is to use bitwise and with negation:
Sometimes you have an offset that identifies your bit, and then the idiom is to use these combined with left-shift:
@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:
Over 10 million iterations, the HasFlags extension method takes a whopping 4793 ms, compared to the 27 ms for the standard bitwise implementation.
To test a bit you would do the following: (assuming flags is a 32 bit number)
Test Bit:
(If bit 4 is set then its true) Toggle Back (1 - 0 or 0 - 1): Reset Bit 4 to Zero:This was inspired by using Sets as indexers in Delphi, way back when:
In .NET 4 you can now write:
.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 toEnum
which helps simplify user's code but unfortunately there are many problems with it.HasFlag
is not type-safe as it accepts any type of enum value argument, not just the given enum type.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.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
orflags.HasFlag(otherFlags)
Enums.NET
flags.HasAllFlags(otherFlags)
Has Any Flags
.NET
(flags & otherFlags) != 0
Enums.NET
flags.HasAnyFlags(otherFlags)
Get Flags
.NET
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.