Related
From time to time I see an enum like the following:
[Flags]
public enum Options
{
None = 0,
Option1 = 1,
Option2 = 2,
Option3 = 4,
Option4 = 8
}
I don't understand what exactly the [Flags] attribute does.
Anyone have a good explanation or example they could post?
The [Flags] attribute should be used whenever the enumerable represents a collection of possible values, rather than a single value. Such collections are often used with bitwise operators, for example:
var allowedColors = MyColor.Red | MyColor.Green | MyColor.Blue;
Note that the [Flags] attribute doesn't enable this by itself - all it does is allow a nice representation by the .ToString() method:
enum Suits { Spades = 1, Clubs = 2, Diamonds = 4, Hearts = 8 }
[Flags] enum SuitsFlags { Spades = 1, Clubs = 2, Diamonds = 4, Hearts = 8 }
...
var str1 = (Suits.Spades | Suits.Diamonds).ToString();
// "5"
var str2 = (SuitsFlags.Spades | SuitsFlags.Diamonds).ToString();
// "Spades, Diamonds"
It is also important to note that [Flags] does not automatically make the enum values powers of two. If you omit the numeric values, the enum will not work as one might expect in bitwise operations, because by default the values start with 0 and increment.
Incorrect declaration:
[Flags]
public enum MyColors
{
Yellow, // 0
Green, // 1
Red, // 2
Blue // 3
}
The values, if declared this way, will be Yellow = 0, Green = 1, Red = 2, Blue = 3. This will render it useless as flags.
Here's an example of a correct declaration:
[Flags]
public enum MyColors
{
Yellow = 1,
Green = 2,
Red = 4,
Blue = 8
}
To retrieve the distinct values in your property, one can do this:
if (myProperties.AllowedColors.HasFlag(MyColor.Yellow))
{
// Yellow is allowed...
}
or prior to .NET 4:
if((myProperties.AllowedColors & MyColor.Yellow) == MyColor.Yellow)
{
// Yellow is allowed...
}
if((myProperties.AllowedColors & MyColor.Green) == MyColor.Green)
{
// Green is allowed...
}
Under the covers
This works because you used powers of two in your enumeration. Under the covers, your enumeration values look like this in binary ones and zeros:
Yellow: 00000001
Green: 00000010
Red: 00000100
Blue: 00001000
Similarly, after you've set your property AllowedColors to Red, Green and Blue using the binary bitwise OR | operator, AllowedColors looks like this:
myProperties.AllowedColors: 00001110
So when you retrieve the value you are actually performing bitwise AND & on the values:
myProperties.AllowedColors: 00001110
MyColor.Green: 00000010
-----------------------
00000010 // Hey, this is the same as MyColor.Green!
The None = 0 value
And regarding the use of 0 in your enumeration, quoting from MSDN:
[Flags]
public enum MyColors
{
None = 0,
....
}
Use None as the name of the flag enumerated constant whose value is zero. You cannot use the None enumerated constant in a bitwise AND operation to test for a flag because the result is always zero. However, you can perform a logical, not a bitwise, comparison between the numeric value and the None enumerated constant to determine whether any bits in the numeric value are set.
You can find more info about the flags attribute and its usage at msdn and designing flags at msdn
You can also do this
[Flags]
public enum MyEnum
{
None = 0,
First = 1 << 0,
Second = 1 << 1,
Third = 1 << 2,
Fourth = 1 << 3
}
I find the bit-shifting easier than typing 4,8,16,32 and so on. It has no impact on your code because it's all done at compile time
Combining answers https://stackoverflow.com/a/8462/1037948 (declaration via bit-shifting) and https://stackoverflow.com/a/9117/1037948 (using combinations in declaration) you can bit-shift previous values rather than using numbers. Not necessarily recommending it, but just pointing out you can.
Rather than:
[Flags]
public enum Options : byte
{
None = 0,
One = 1 << 0, // 1
Two = 1 << 1, // 2
Three = 1 << 2, // 4
Four = 1 << 3, // 8
// combinations
OneAndTwo = One | Two,
OneTwoAndThree = One | Two | Three,
}
You can declare
[Flags]
public enum Options : byte
{
None = 0,
One = 1 << 0, // 1
// now that value 1 is available, start shifting from there
Two = One << 1, // 2
Three = Two << 1, // 4
Four = Three << 1, // 8
// same combinations
OneAndTwo = One | Two,
OneTwoAndThree = One | Two | Three,
}
Confirming with LinqPad:
foreach(var e in Enum.GetValues(typeof(Options))) {
string.Format("{0} = {1}", e.ToString(), (byte)e).Dump();
}
Results in:
None = 0
One = 1
Two = 2
OneAndTwo = 3
Three = 4
OneTwoAndThree = 7
Four = 8
In extension to the accepted answer, in C#7 the enum flags can be written using binary literals:
[Flags]
public enum MyColors
{
None = 0b0000,
Yellow = 0b0001,
Green = 0b0010,
Red = 0b0100,
Blue = 0b1000
}
I think this representation makes it clear how the flags work under the covers.
Please see the following for an example which shows the declaration and potential usage:
namespace Flags
{
class Program
{
[Flags]
public enum MyFlags : short
{
Foo = 0x1,
Bar = 0x2,
Baz = 0x4
}
static void Main(string[] args)
{
MyFlags fooBar = MyFlags.Foo | MyFlags.Bar;
if ((fooBar & MyFlags.Foo) == MyFlags.Foo)
{
Console.WriteLine("Item has Foo flag set");
}
}
}
}
I asked recently about something similar.
If you use flags you can add an extension method to enums to make checking the contained flags easier (see post for detail)
This allows you to do:
[Flags]
public enum PossibleOptions : byte
{
None = 0,
OptionOne = 1,
OptionTwo = 2,
OptionThree = 4,
OptionFour = 8,
//combinations can be in the enum too
OptionOneAndTwo = OptionOne | OptionTwo,
OptionOneTwoAndThree = OptionOne | OptionTwo | OptionThree,
...
}
Then you can do:
PossibleOptions opt = PossibleOptions.OptionOneTwoAndThree
if( opt.IsSet( PossibleOptions.OptionOne ) ) {
//optionOne is one of those set
}
I find this easier to read than the most ways of checking the included flags.
When working with flags I often declare additional None and All items. These are helpful to check whether all flags are set or no flag is set.
[Flags]
enum SuitsFlags {
None = 0,
Spades = 1 << 0,
Clubs = 1 << 1,
Diamonds = 1 << 2,
Hearts = 1 << 3,
All = ~(~0 << 4)
}
Usage:
Spades | Clubs | Diamonds | Hearts == All // true
Spades & Clubs == None // true
Update 2019-10:
Since C# 7.0 you can use binary literals, which are probably more intuitive to read:
[Flags]
enum SuitsFlags {
None = 0b0000,
Spades = 0b0001,
Clubs = 0b0010,
Diamonds = 0b0100,
Hearts = 0b1000,
All = 0b1111
}
#Nidonocu
To add another flag to an existing set of values, use the OR assignment operator.
Mode = Mode.Read;
//Add Mode.Write
Mode |= Mode.Write;
Assert.True(((Mode & Mode.Write) == Mode.Write)
&& ((Mode & Mode.Read) == Mode.Read)));
To add Mode.Write:
Mode = Mode | Mode.Write;
There's something overly verbose to me about the if ((x & y) == y)... construct, especially if x AND y are both compound sets of flags and you only want to know if there's any overlap.
In this case, all you really need to know is if there's a non-zero value[1] after you've bitmasked.
[1] See Jaime's comment. If we were authentically bitmasking, we'd
only need to check that the result was positive. But since enums
can be negative, even, strangely, when combined with the [Flags]
attribute,
it's defensive to code for != 0 rather than > 0.
Building off of #andnil's setup...
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BitFlagPlay
{
class Program
{
[Flags]
public enum MyColor
{
Yellow = 0x01,
Green = 0x02,
Red = 0x04,
Blue = 0x08
}
static void Main(string[] args)
{
var myColor = MyColor.Yellow | MyColor.Blue;
var acceptableColors = MyColor.Yellow | MyColor.Red;
Console.WriteLine((myColor & MyColor.Blue) != 0); // True
Console.WriteLine((myColor & MyColor.Red) != 0); // False
Console.WriteLine((myColor & acceptableColors) != 0); // True
// ... though only Yellow is shared.
Console.WriteLine((myColor & MyColor.Green) != 0); // Wait a minute... ;^D
Console.Read();
}
}
}
Flags allow you to use bitmasking inside your enumeration. This allows you to combine enumeration values, while retaining which ones are specified.
[Flags]
public enum DashboardItemPresentationProperties : long
{
None = 0,
HideCollapse = 1,
HideDelete = 2,
HideEdit = 4,
HideOpenInNewWindow = 8,
HideResetSource = 16,
HideMenu = 32
}
Apologies if someone already noticed this scenario. A perfect example of flags we can see in reflection. Yes Binding Flags ENUM.
[System.Flags]
[System.Runtime.InteropServices.ComVisible(true)]
[System.Serializable]
public enum BindingFlags
Usage
// BindingFlags.InvokeMethod
// Call a static method.
Type t = typeof (TestClass);
Console.WriteLine();
Console.WriteLine("Invoking a static method.");
Console.WriteLine("-------------------------");
t.InvokeMember ("SayHello", BindingFlags.InvokeMethod | BindingFlags.Public |
BindingFlags.Static, null, null, new object [] {});
Define the Problem
Let’s define an enum that represents the types of users:
public enum UserType
{
Customer = 1,
Driver = 2,
Admin = 3,
}
We define the UserType enum that contains three values: Customer, Driver, and Admin.
But what if we need to represent a collection of values?
For example, at a delivery company, we know that both the Admin and the Driver are employees. So let’s add a new enumeration item Employee. Later on, we will show you how we can represent both the admin and the driver with it:
public enum UserType
{
Customer = 1,
Driver = 2,
Admin = 3,
Employee = 4
}
Define and Declare a Flags Attribute
A Flags is an attribute that allows us to represent an enum as a collection of values rather than a single value. So, let’s see how we can implement the Flags attribute on enumeration:
[Flags]
public enum UserType
{
Customer = 1,
Driver = 2,
Admin = 4,
}
We add the Flags attribute and number the values with powers of 2. Without both, this won’t work.
Now going back to our previous problem, we can represent Employee using the | operator:
var employee = UserType.Driver | UserType.Admin;
Also, we can define it as a constant inside the enum to use it directly:
[Flags]
public enum UserType
{
Customer = 1,
Driver = 2,
Admin = 4,
Employee = Driver | Admin
}
Behind the Scenes
To understand the Flags attribute better, we must go back to the binary representation of the number. For example, we can represent 1 as binary 0b_0001 and 2 as 0b_0010:
[Flags]
public enum UserType
{
Customer = 0b_0001,
Driver = 0b_0010,
Admin = 0b_0100,
Employee = Driver | Admin, //0b_0110
}
We can see that each value is represented in an active bit. And this is where the idea of numbering the values with the power of 2 came from. We can also note that Employee contains two active bits, that is, it is a composite of two values Driver and Admin.
Operations on Flags Attribute
We can use the bitwise operators to work with Flags.
Initialize a Value
For the initialization, we should use the value 0 named None, which means the collection is empty:
[Flags]
public enum UserType
{
None = 0,
Customer = 1,
Driver = 2,
Admin = 4,
Employee = Driver | Admin
}
Now, we can define a variable:
var flags = UserType.None;
Add a Value
We can add value by using | operator:
flags |= UserType.Driver;
Now, the flags variable equals Driver.
Remove a Value
We can remove value by use &, ~ operators:
flags &= ~UserType.Driver;
Now, flagsvariable equals None.
We can check if the value exists by using & operator:
Console.WriteLine((flags & UserType.Driver) == UserType.Driver);
The result is False.
Also, we can do this by using the HasFlag method:
Console.WriteLine(flags.HasFlag(UserType.Driver));
Also, the result will be False.
As we can see, both ways, using the & operator and the HasFlag method, give the same result, but which one should we use? To find out, we will test the performance on several frameworks.
Measure the Performance
First, we will create a Console App, and in the .csproj file we will replace the TargetFramwork tag with the TargetFramworks tag:
<TargetFrameworks>net48;netcoreapp3.1;net6.0</TargetFrameworks>
We use the TargetFramworks tag to support multiple frameworks: .NET Framework 4.8, .Net Core 3.1, and .Net 6.0.
Secondly, let’s introduce the BenchmarkDotNet library to get the benchmark results:
[Benchmark]
public bool HasFlag()
{
var result = false;
for (int i = 0; i < 100000; i++)
{
result = UserType.Employee.HasFlag(UserType.Driver);
}
return result;
}
[Benchmark]
public bool BitOperator()
{
var result = false;
for (int i = 0; i < 100000; i++)
{
result = (UserType.Employee & UserType.Driver) == UserType.Driver;
}
return result;
}
We add [SimpleJob(RuntimeMoniker.Net48)], [SimpleJob(RuntimeMoniker.NetCoreApp31)], and [SimpleJob(RuntimeMoniker.Net60)] attributes to the HasFlagBenchmarker class to see the performance differences between different versions of .NET Framework / .NET Core:
Method
Job
Runtime
Mean
Error
StdDev
Median
HasFlag
.NET 6.0
.NET 6.0
37.79 us
3.781 us
11.15 us
30.30 us
BitOperator
.NET 6.0
.NET 6.0
38.17 us
3.853 us
11.36 us
30.38 us
HasFlag
.NET Core 3.1
.NET Core 3.1
38.31 us
3.939 us
11.61 us
30.37 us
BitOperator
.NET Core 3.1
.NET Core 3.1
38.07 us
3.819 us
11.26 us
30.33 us
HasFlag
.NET Framework 4.8
.NET Framework 4.8
2,893.10 us
342.563 us
1,010.06 us
2,318.93 us
BitOperator
.NET Framework 4.8
.NET Framework 4.8
38.04 us
3.920 us
11.56 us
30.17 us
So, in .NET Framework 4.8 a HasFlag method was much slower than the BitOperator. But, the performance improves in .Net Core 3.1 and .Net 6.0. So in newer versions, we can use both ways.
Flags are used when an enumerable value represents a collection of
enum members.
here we use bitwise operators, | and &
Example
[Flags]
public enum Sides { Left=0, Right=1, Top=2, Bottom=3 }
Sides leftRight = Sides.Left | Sides.Right;
Console.WriteLine (leftRight);//Left, Right
string stringValue = leftRight.ToString();
Console.WriteLine (stringValue);//Left, Right
Sides s = Sides.Left;
s |= Sides.Right;
Console.WriteLine (s);//Left, Right
s ^= Sides.Right; // Toggles Sides.Right
Console.WriteLine (s); //Left
From time to time I see an enum like the following:
[Flags]
public enum Options
{
None = 0,
Option1 = 1,
Option2 = 2,
Option3 = 4,
Option4 = 8
}
I don't understand what exactly the [Flags] attribute does.
Anyone have a good explanation or example they could post?
The [Flags] attribute should be used whenever the enumerable represents a collection of possible values, rather than a single value. Such collections are often used with bitwise operators, for example:
var allowedColors = MyColor.Red | MyColor.Green | MyColor.Blue;
Note that the [Flags] attribute doesn't enable this by itself - all it does is allow a nice representation by the .ToString() method:
enum Suits { Spades = 1, Clubs = 2, Diamonds = 4, Hearts = 8 }
[Flags] enum SuitsFlags { Spades = 1, Clubs = 2, Diamonds = 4, Hearts = 8 }
...
var str1 = (Suits.Spades | Suits.Diamonds).ToString();
// "5"
var str2 = (SuitsFlags.Spades | SuitsFlags.Diamonds).ToString();
// "Spades, Diamonds"
It is also important to note that [Flags] does not automatically make the enum values powers of two. If you omit the numeric values, the enum will not work as one might expect in bitwise operations, because by default the values start with 0 and increment.
Incorrect declaration:
[Flags]
public enum MyColors
{
Yellow, // 0
Green, // 1
Red, // 2
Blue // 3
}
The values, if declared this way, will be Yellow = 0, Green = 1, Red = 2, Blue = 3. This will render it useless as flags.
Here's an example of a correct declaration:
[Flags]
public enum MyColors
{
Yellow = 1,
Green = 2,
Red = 4,
Blue = 8
}
To retrieve the distinct values in your property, one can do this:
if (myProperties.AllowedColors.HasFlag(MyColor.Yellow))
{
// Yellow is allowed...
}
or prior to .NET 4:
if((myProperties.AllowedColors & MyColor.Yellow) == MyColor.Yellow)
{
// Yellow is allowed...
}
if((myProperties.AllowedColors & MyColor.Green) == MyColor.Green)
{
// Green is allowed...
}
Under the covers
This works because you used powers of two in your enumeration. Under the covers, your enumeration values look like this in binary ones and zeros:
Yellow: 00000001
Green: 00000010
Red: 00000100
Blue: 00001000
Similarly, after you've set your property AllowedColors to Red, Green and Blue using the binary bitwise OR | operator, AllowedColors looks like this:
myProperties.AllowedColors: 00001110
So when you retrieve the value you are actually performing bitwise AND & on the values:
myProperties.AllowedColors: 00001110
MyColor.Green: 00000010
-----------------------
00000010 // Hey, this is the same as MyColor.Green!
The None = 0 value
And regarding the use of 0 in your enumeration, quoting from MSDN:
[Flags]
public enum MyColors
{
None = 0,
....
}
Use None as the name of the flag enumerated constant whose value is zero. You cannot use the None enumerated constant in a bitwise AND operation to test for a flag because the result is always zero. However, you can perform a logical, not a bitwise, comparison between the numeric value and the None enumerated constant to determine whether any bits in the numeric value are set.
You can find more info about the flags attribute and its usage at msdn and designing flags at msdn
You can also do this
[Flags]
public enum MyEnum
{
None = 0,
First = 1 << 0,
Second = 1 << 1,
Third = 1 << 2,
Fourth = 1 << 3
}
I find the bit-shifting easier than typing 4,8,16,32 and so on. It has no impact on your code because it's all done at compile time
Combining answers https://stackoverflow.com/a/8462/1037948 (declaration via bit-shifting) and https://stackoverflow.com/a/9117/1037948 (using combinations in declaration) you can bit-shift previous values rather than using numbers. Not necessarily recommending it, but just pointing out you can.
Rather than:
[Flags]
public enum Options : byte
{
None = 0,
One = 1 << 0, // 1
Two = 1 << 1, // 2
Three = 1 << 2, // 4
Four = 1 << 3, // 8
// combinations
OneAndTwo = One | Two,
OneTwoAndThree = One | Two | Three,
}
You can declare
[Flags]
public enum Options : byte
{
None = 0,
One = 1 << 0, // 1
// now that value 1 is available, start shifting from there
Two = One << 1, // 2
Three = Two << 1, // 4
Four = Three << 1, // 8
// same combinations
OneAndTwo = One | Two,
OneTwoAndThree = One | Two | Three,
}
Confirming with LinqPad:
foreach(var e in Enum.GetValues(typeof(Options))) {
string.Format("{0} = {1}", e.ToString(), (byte)e).Dump();
}
Results in:
None = 0
One = 1
Two = 2
OneAndTwo = 3
Three = 4
OneTwoAndThree = 7
Four = 8
In extension to the accepted answer, in C#7 the enum flags can be written using binary literals:
[Flags]
public enum MyColors
{
None = 0b0000,
Yellow = 0b0001,
Green = 0b0010,
Red = 0b0100,
Blue = 0b1000
}
I think this representation makes it clear how the flags work under the covers.
Please see the following for an example which shows the declaration and potential usage:
namespace Flags
{
class Program
{
[Flags]
public enum MyFlags : short
{
Foo = 0x1,
Bar = 0x2,
Baz = 0x4
}
static void Main(string[] args)
{
MyFlags fooBar = MyFlags.Foo | MyFlags.Bar;
if ((fooBar & MyFlags.Foo) == MyFlags.Foo)
{
Console.WriteLine("Item has Foo flag set");
}
}
}
}
I asked recently about something similar.
If you use flags you can add an extension method to enums to make checking the contained flags easier (see post for detail)
This allows you to do:
[Flags]
public enum PossibleOptions : byte
{
None = 0,
OptionOne = 1,
OptionTwo = 2,
OptionThree = 4,
OptionFour = 8,
//combinations can be in the enum too
OptionOneAndTwo = OptionOne | OptionTwo,
OptionOneTwoAndThree = OptionOne | OptionTwo | OptionThree,
...
}
Then you can do:
PossibleOptions opt = PossibleOptions.OptionOneTwoAndThree
if( opt.IsSet( PossibleOptions.OptionOne ) ) {
//optionOne is one of those set
}
I find this easier to read than the most ways of checking the included flags.
When working with flags I often declare additional None and All items. These are helpful to check whether all flags are set or no flag is set.
[Flags]
enum SuitsFlags {
None = 0,
Spades = 1 << 0,
Clubs = 1 << 1,
Diamonds = 1 << 2,
Hearts = 1 << 3,
All = ~(~0 << 4)
}
Usage:
Spades | Clubs | Diamonds | Hearts == All // true
Spades & Clubs == None // true
Update 2019-10:
Since C# 7.0 you can use binary literals, which are probably more intuitive to read:
[Flags]
enum SuitsFlags {
None = 0b0000,
Spades = 0b0001,
Clubs = 0b0010,
Diamonds = 0b0100,
Hearts = 0b1000,
All = 0b1111
}
#Nidonocu
To add another flag to an existing set of values, use the OR assignment operator.
Mode = Mode.Read;
//Add Mode.Write
Mode |= Mode.Write;
Assert.True(((Mode & Mode.Write) == Mode.Write)
&& ((Mode & Mode.Read) == Mode.Read)));
To add Mode.Write:
Mode = Mode | Mode.Write;
There's something overly verbose to me about the if ((x & y) == y)... construct, especially if x AND y are both compound sets of flags and you only want to know if there's any overlap.
In this case, all you really need to know is if there's a non-zero value[1] after you've bitmasked.
[1] See Jaime's comment. If we were authentically bitmasking, we'd
only need to check that the result was positive. But since enums
can be negative, even, strangely, when combined with the [Flags]
attribute,
it's defensive to code for != 0 rather than > 0.
Building off of #andnil's setup...
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BitFlagPlay
{
class Program
{
[Flags]
public enum MyColor
{
Yellow = 0x01,
Green = 0x02,
Red = 0x04,
Blue = 0x08
}
static void Main(string[] args)
{
var myColor = MyColor.Yellow | MyColor.Blue;
var acceptableColors = MyColor.Yellow | MyColor.Red;
Console.WriteLine((myColor & MyColor.Blue) != 0); // True
Console.WriteLine((myColor & MyColor.Red) != 0); // False
Console.WriteLine((myColor & acceptableColors) != 0); // True
// ... though only Yellow is shared.
Console.WriteLine((myColor & MyColor.Green) != 0); // Wait a minute... ;^D
Console.Read();
}
}
}
Flags allow you to use bitmasking inside your enumeration. This allows you to combine enumeration values, while retaining which ones are specified.
[Flags]
public enum DashboardItemPresentationProperties : long
{
None = 0,
HideCollapse = 1,
HideDelete = 2,
HideEdit = 4,
HideOpenInNewWindow = 8,
HideResetSource = 16,
HideMenu = 32
}
Apologies if someone already noticed this scenario. A perfect example of flags we can see in reflection. Yes Binding Flags ENUM.
[System.Flags]
[System.Runtime.InteropServices.ComVisible(true)]
[System.Serializable]
public enum BindingFlags
Usage
// BindingFlags.InvokeMethod
// Call a static method.
Type t = typeof (TestClass);
Console.WriteLine();
Console.WriteLine("Invoking a static method.");
Console.WriteLine("-------------------------");
t.InvokeMember ("SayHello", BindingFlags.InvokeMethod | BindingFlags.Public |
BindingFlags.Static, null, null, new object [] {});
Define the Problem
Let’s define an enum that represents the types of users:
public enum UserType
{
Customer = 1,
Driver = 2,
Admin = 3,
}
We define the UserType enum that contains three values: Customer, Driver, and Admin.
But what if we need to represent a collection of values?
For example, at a delivery company, we know that both the Admin and the Driver are employees. So let’s add a new enumeration item Employee. Later on, we will show you how we can represent both the admin and the driver with it:
public enum UserType
{
Customer = 1,
Driver = 2,
Admin = 3,
Employee = 4
}
Define and Declare a Flags Attribute
A Flags is an attribute that allows us to represent an enum as a collection of values rather than a single value. So, let’s see how we can implement the Flags attribute on enumeration:
[Flags]
public enum UserType
{
Customer = 1,
Driver = 2,
Admin = 4,
}
We add the Flags attribute and number the values with powers of 2. Without both, this won’t work.
Now going back to our previous problem, we can represent Employee using the | operator:
var employee = UserType.Driver | UserType.Admin;
Also, we can define it as a constant inside the enum to use it directly:
[Flags]
public enum UserType
{
Customer = 1,
Driver = 2,
Admin = 4,
Employee = Driver | Admin
}
Behind the Scenes
To understand the Flags attribute better, we must go back to the binary representation of the number. For example, we can represent 1 as binary 0b_0001 and 2 as 0b_0010:
[Flags]
public enum UserType
{
Customer = 0b_0001,
Driver = 0b_0010,
Admin = 0b_0100,
Employee = Driver | Admin, //0b_0110
}
We can see that each value is represented in an active bit. And this is where the idea of numbering the values with the power of 2 came from. We can also note that Employee contains two active bits, that is, it is a composite of two values Driver and Admin.
Operations on Flags Attribute
We can use the bitwise operators to work with Flags.
Initialize a Value
For the initialization, we should use the value 0 named None, which means the collection is empty:
[Flags]
public enum UserType
{
None = 0,
Customer = 1,
Driver = 2,
Admin = 4,
Employee = Driver | Admin
}
Now, we can define a variable:
var flags = UserType.None;
Add a Value
We can add value by using | operator:
flags |= UserType.Driver;
Now, the flags variable equals Driver.
Remove a Value
We can remove value by use &, ~ operators:
flags &= ~UserType.Driver;
Now, flagsvariable equals None.
We can check if the value exists by using & operator:
Console.WriteLine((flags & UserType.Driver) == UserType.Driver);
The result is False.
Also, we can do this by using the HasFlag method:
Console.WriteLine(flags.HasFlag(UserType.Driver));
Also, the result will be False.
As we can see, both ways, using the & operator and the HasFlag method, give the same result, but which one should we use? To find out, we will test the performance on several frameworks.
Measure the Performance
First, we will create a Console App, and in the .csproj file we will replace the TargetFramwork tag with the TargetFramworks tag:
<TargetFrameworks>net48;netcoreapp3.1;net6.0</TargetFrameworks>
We use the TargetFramworks tag to support multiple frameworks: .NET Framework 4.8, .Net Core 3.1, and .Net 6.0.
Secondly, let’s introduce the BenchmarkDotNet library to get the benchmark results:
[Benchmark]
public bool HasFlag()
{
var result = false;
for (int i = 0; i < 100000; i++)
{
result = UserType.Employee.HasFlag(UserType.Driver);
}
return result;
}
[Benchmark]
public bool BitOperator()
{
var result = false;
for (int i = 0; i < 100000; i++)
{
result = (UserType.Employee & UserType.Driver) == UserType.Driver;
}
return result;
}
We add [SimpleJob(RuntimeMoniker.Net48)], [SimpleJob(RuntimeMoniker.NetCoreApp31)], and [SimpleJob(RuntimeMoniker.Net60)] attributes to the HasFlagBenchmarker class to see the performance differences between different versions of .NET Framework / .NET Core:
Method
Job
Runtime
Mean
Error
StdDev
Median
HasFlag
.NET 6.0
.NET 6.0
37.79 us
3.781 us
11.15 us
30.30 us
BitOperator
.NET 6.0
.NET 6.0
38.17 us
3.853 us
11.36 us
30.38 us
HasFlag
.NET Core 3.1
.NET Core 3.1
38.31 us
3.939 us
11.61 us
30.37 us
BitOperator
.NET Core 3.1
.NET Core 3.1
38.07 us
3.819 us
11.26 us
30.33 us
HasFlag
.NET Framework 4.8
.NET Framework 4.8
2,893.10 us
342.563 us
1,010.06 us
2,318.93 us
BitOperator
.NET Framework 4.8
.NET Framework 4.8
38.04 us
3.920 us
11.56 us
30.17 us
So, in .NET Framework 4.8 a HasFlag method was much slower than the BitOperator. But, the performance improves in .Net Core 3.1 and .Net 6.0. So in newer versions, we can use both ways.
Flags are used when an enumerable value represents a collection of
enum members.
here we use bitwise operators, | and &
Example
[Flags]
public enum Sides { Left=0, Right=1, Top=2, Bottom=3 }
Sides leftRight = Sides.Left | Sides.Right;
Console.WriteLine (leftRight);//Left, Right
string stringValue = leftRight.ToString();
Console.WriteLine (stringValue);//Left, Right
Sides s = Sides.Left;
s |= Sides.Right;
Console.WriteLine (s);//Left, Right
s ^= Sides.Right; // Toggles Sides.Right
Console.WriteLine (s); //Left
From time to time I see an enum like the following:
[Flags]
public enum Options
{
None = 0,
Option1 = 1,
Option2 = 2,
Option3 = 4,
Option4 = 8
}
I don't understand what exactly the [Flags] attribute does.
Anyone have a good explanation or example they could post?
The [Flags] attribute should be used whenever the enumerable represents a collection of possible values, rather than a single value. Such collections are often used with bitwise operators, for example:
var allowedColors = MyColor.Red | MyColor.Green | MyColor.Blue;
Note that the [Flags] attribute doesn't enable this by itself - all it does is allow a nice representation by the .ToString() method:
enum Suits { Spades = 1, Clubs = 2, Diamonds = 4, Hearts = 8 }
[Flags] enum SuitsFlags { Spades = 1, Clubs = 2, Diamonds = 4, Hearts = 8 }
...
var str1 = (Suits.Spades | Suits.Diamonds).ToString();
// "5"
var str2 = (SuitsFlags.Spades | SuitsFlags.Diamonds).ToString();
// "Spades, Diamonds"
It is also important to note that [Flags] does not automatically make the enum values powers of two. If you omit the numeric values, the enum will not work as one might expect in bitwise operations, because by default the values start with 0 and increment.
Incorrect declaration:
[Flags]
public enum MyColors
{
Yellow, // 0
Green, // 1
Red, // 2
Blue // 3
}
The values, if declared this way, will be Yellow = 0, Green = 1, Red = 2, Blue = 3. This will render it useless as flags.
Here's an example of a correct declaration:
[Flags]
public enum MyColors
{
Yellow = 1,
Green = 2,
Red = 4,
Blue = 8
}
To retrieve the distinct values in your property, one can do this:
if (myProperties.AllowedColors.HasFlag(MyColor.Yellow))
{
// Yellow is allowed...
}
or prior to .NET 4:
if((myProperties.AllowedColors & MyColor.Yellow) == MyColor.Yellow)
{
// Yellow is allowed...
}
if((myProperties.AllowedColors & MyColor.Green) == MyColor.Green)
{
// Green is allowed...
}
Under the covers
This works because you used powers of two in your enumeration. Under the covers, your enumeration values look like this in binary ones and zeros:
Yellow: 00000001
Green: 00000010
Red: 00000100
Blue: 00001000
Similarly, after you've set your property AllowedColors to Red, Green and Blue using the binary bitwise OR | operator, AllowedColors looks like this:
myProperties.AllowedColors: 00001110
So when you retrieve the value you are actually performing bitwise AND & on the values:
myProperties.AllowedColors: 00001110
MyColor.Green: 00000010
-----------------------
00000010 // Hey, this is the same as MyColor.Green!
The None = 0 value
And regarding the use of 0 in your enumeration, quoting from MSDN:
[Flags]
public enum MyColors
{
None = 0,
....
}
Use None as the name of the flag enumerated constant whose value is zero. You cannot use the None enumerated constant in a bitwise AND operation to test for a flag because the result is always zero. However, you can perform a logical, not a bitwise, comparison between the numeric value and the None enumerated constant to determine whether any bits in the numeric value are set.
You can find more info about the flags attribute and its usage at msdn and designing flags at msdn
You can also do this
[Flags]
public enum MyEnum
{
None = 0,
First = 1 << 0,
Second = 1 << 1,
Third = 1 << 2,
Fourth = 1 << 3
}
I find the bit-shifting easier than typing 4,8,16,32 and so on. It has no impact on your code because it's all done at compile time
Combining answers https://stackoverflow.com/a/8462/1037948 (declaration via bit-shifting) and https://stackoverflow.com/a/9117/1037948 (using combinations in declaration) you can bit-shift previous values rather than using numbers. Not necessarily recommending it, but just pointing out you can.
Rather than:
[Flags]
public enum Options : byte
{
None = 0,
One = 1 << 0, // 1
Two = 1 << 1, // 2
Three = 1 << 2, // 4
Four = 1 << 3, // 8
// combinations
OneAndTwo = One | Two,
OneTwoAndThree = One | Two | Three,
}
You can declare
[Flags]
public enum Options : byte
{
None = 0,
One = 1 << 0, // 1
// now that value 1 is available, start shifting from there
Two = One << 1, // 2
Three = Two << 1, // 4
Four = Three << 1, // 8
// same combinations
OneAndTwo = One | Two,
OneTwoAndThree = One | Two | Three,
}
Confirming with LinqPad:
foreach(var e in Enum.GetValues(typeof(Options))) {
string.Format("{0} = {1}", e.ToString(), (byte)e).Dump();
}
Results in:
None = 0
One = 1
Two = 2
OneAndTwo = 3
Three = 4
OneTwoAndThree = 7
Four = 8
In extension to the accepted answer, in C#7 the enum flags can be written using binary literals:
[Flags]
public enum MyColors
{
None = 0b0000,
Yellow = 0b0001,
Green = 0b0010,
Red = 0b0100,
Blue = 0b1000
}
I think this representation makes it clear how the flags work under the covers.
Please see the following for an example which shows the declaration and potential usage:
namespace Flags
{
class Program
{
[Flags]
public enum MyFlags : short
{
Foo = 0x1,
Bar = 0x2,
Baz = 0x4
}
static void Main(string[] args)
{
MyFlags fooBar = MyFlags.Foo | MyFlags.Bar;
if ((fooBar & MyFlags.Foo) == MyFlags.Foo)
{
Console.WriteLine("Item has Foo flag set");
}
}
}
}
I asked recently about something similar.
If you use flags you can add an extension method to enums to make checking the contained flags easier (see post for detail)
This allows you to do:
[Flags]
public enum PossibleOptions : byte
{
None = 0,
OptionOne = 1,
OptionTwo = 2,
OptionThree = 4,
OptionFour = 8,
//combinations can be in the enum too
OptionOneAndTwo = OptionOne | OptionTwo,
OptionOneTwoAndThree = OptionOne | OptionTwo | OptionThree,
...
}
Then you can do:
PossibleOptions opt = PossibleOptions.OptionOneTwoAndThree
if( opt.IsSet( PossibleOptions.OptionOne ) ) {
//optionOne is one of those set
}
I find this easier to read than the most ways of checking the included flags.
When working with flags I often declare additional None and All items. These are helpful to check whether all flags are set or no flag is set.
[Flags]
enum SuitsFlags {
None = 0,
Spades = 1 << 0,
Clubs = 1 << 1,
Diamonds = 1 << 2,
Hearts = 1 << 3,
All = ~(~0 << 4)
}
Usage:
Spades | Clubs | Diamonds | Hearts == All // true
Spades & Clubs == None // true
Update 2019-10:
Since C# 7.0 you can use binary literals, which are probably more intuitive to read:
[Flags]
enum SuitsFlags {
None = 0b0000,
Spades = 0b0001,
Clubs = 0b0010,
Diamonds = 0b0100,
Hearts = 0b1000,
All = 0b1111
}
#Nidonocu
To add another flag to an existing set of values, use the OR assignment operator.
Mode = Mode.Read;
//Add Mode.Write
Mode |= Mode.Write;
Assert.True(((Mode & Mode.Write) == Mode.Write)
&& ((Mode & Mode.Read) == Mode.Read)));
To add Mode.Write:
Mode = Mode | Mode.Write;
There's something overly verbose to me about the if ((x & y) == y)... construct, especially if x AND y are both compound sets of flags and you only want to know if there's any overlap.
In this case, all you really need to know is if there's a non-zero value[1] after you've bitmasked.
[1] See Jaime's comment. If we were authentically bitmasking, we'd
only need to check that the result was positive. But since enums
can be negative, even, strangely, when combined with the [Flags]
attribute,
it's defensive to code for != 0 rather than > 0.
Building off of #andnil's setup...
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BitFlagPlay
{
class Program
{
[Flags]
public enum MyColor
{
Yellow = 0x01,
Green = 0x02,
Red = 0x04,
Blue = 0x08
}
static void Main(string[] args)
{
var myColor = MyColor.Yellow | MyColor.Blue;
var acceptableColors = MyColor.Yellow | MyColor.Red;
Console.WriteLine((myColor & MyColor.Blue) != 0); // True
Console.WriteLine((myColor & MyColor.Red) != 0); // False
Console.WriteLine((myColor & acceptableColors) != 0); // True
// ... though only Yellow is shared.
Console.WriteLine((myColor & MyColor.Green) != 0); // Wait a minute... ;^D
Console.Read();
}
}
}
Flags allow you to use bitmasking inside your enumeration. This allows you to combine enumeration values, while retaining which ones are specified.
[Flags]
public enum DashboardItemPresentationProperties : long
{
None = 0,
HideCollapse = 1,
HideDelete = 2,
HideEdit = 4,
HideOpenInNewWindow = 8,
HideResetSource = 16,
HideMenu = 32
}
Apologies if someone already noticed this scenario. A perfect example of flags we can see in reflection. Yes Binding Flags ENUM.
[System.Flags]
[System.Runtime.InteropServices.ComVisible(true)]
[System.Serializable]
public enum BindingFlags
Usage
// BindingFlags.InvokeMethod
// Call a static method.
Type t = typeof (TestClass);
Console.WriteLine();
Console.WriteLine("Invoking a static method.");
Console.WriteLine("-------------------------");
t.InvokeMember ("SayHello", BindingFlags.InvokeMethod | BindingFlags.Public |
BindingFlags.Static, null, null, new object [] {});
Define the Problem
Let’s define an enum that represents the types of users:
public enum UserType
{
Customer = 1,
Driver = 2,
Admin = 3,
}
We define the UserType enum that contains three values: Customer, Driver, and Admin.
But what if we need to represent a collection of values?
For example, at a delivery company, we know that both the Admin and the Driver are employees. So let’s add a new enumeration item Employee. Later on, we will show you how we can represent both the admin and the driver with it:
public enum UserType
{
Customer = 1,
Driver = 2,
Admin = 3,
Employee = 4
}
Define and Declare a Flags Attribute
A Flags is an attribute that allows us to represent an enum as a collection of values rather than a single value. So, let’s see how we can implement the Flags attribute on enumeration:
[Flags]
public enum UserType
{
Customer = 1,
Driver = 2,
Admin = 4,
}
We add the Flags attribute and number the values with powers of 2. Without both, this won’t work.
Now going back to our previous problem, we can represent Employee using the | operator:
var employee = UserType.Driver | UserType.Admin;
Also, we can define it as a constant inside the enum to use it directly:
[Flags]
public enum UserType
{
Customer = 1,
Driver = 2,
Admin = 4,
Employee = Driver | Admin
}
Behind the Scenes
To understand the Flags attribute better, we must go back to the binary representation of the number. For example, we can represent 1 as binary 0b_0001 and 2 as 0b_0010:
[Flags]
public enum UserType
{
Customer = 0b_0001,
Driver = 0b_0010,
Admin = 0b_0100,
Employee = Driver | Admin, //0b_0110
}
We can see that each value is represented in an active bit. And this is where the idea of numbering the values with the power of 2 came from. We can also note that Employee contains two active bits, that is, it is a composite of two values Driver and Admin.
Operations on Flags Attribute
We can use the bitwise operators to work with Flags.
Initialize a Value
For the initialization, we should use the value 0 named None, which means the collection is empty:
[Flags]
public enum UserType
{
None = 0,
Customer = 1,
Driver = 2,
Admin = 4,
Employee = Driver | Admin
}
Now, we can define a variable:
var flags = UserType.None;
Add a Value
We can add value by using | operator:
flags |= UserType.Driver;
Now, the flags variable equals Driver.
Remove a Value
We can remove value by use &, ~ operators:
flags &= ~UserType.Driver;
Now, flagsvariable equals None.
We can check if the value exists by using & operator:
Console.WriteLine((flags & UserType.Driver) == UserType.Driver);
The result is False.
Also, we can do this by using the HasFlag method:
Console.WriteLine(flags.HasFlag(UserType.Driver));
Also, the result will be False.
As we can see, both ways, using the & operator and the HasFlag method, give the same result, but which one should we use? To find out, we will test the performance on several frameworks.
Measure the Performance
First, we will create a Console App, and in the .csproj file we will replace the TargetFramwork tag with the TargetFramworks tag:
<TargetFrameworks>net48;netcoreapp3.1;net6.0</TargetFrameworks>
We use the TargetFramworks tag to support multiple frameworks: .NET Framework 4.8, .Net Core 3.1, and .Net 6.0.
Secondly, let’s introduce the BenchmarkDotNet library to get the benchmark results:
[Benchmark]
public bool HasFlag()
{
var result = false;
for (int i = 0; i < 100000; i++)
{
result = UserType.Employee.HasFlag(UserType.Driver);
}
return result;
}
[Benchmark]
public bool BitOperator()
{
var result = false;
for (int i = 0; i < 100000; i++)
{
result = (UserType.Employee & UserType.Driver) == UserType.Driver;
}
return result;
}
We add [SimpleJob(RuntimeMoniker.Net48)], [SimpleJob(RuntimeMoniker.NetCoreApp31)], and [SimpleJob(RuntimeMoniker.Net60)] attributes to the HasFlagBenchmarker class to see the performance differences between different versions of .NET Framework / .NET Core:
Method
Job
Runtime
Mean
Error
StdDev
Median
HasFlag
.NET 6.0
.NET 6.0
37.79 us
3.781 us
11.15 us
30.30 us
BitOperator
.NET 6.0
.NET 6.0
38.17 us
3.853 us
11.36 us
30.38 us
HasFlag
.NET Core 3.1
.NET Core 3.1
38.31 us
3.939 us
11.61 us
30.37 us
BitOperator
.NET Core 3.1
.NET Core 3.1
38.07 us
3.819 us
11.26 us
30.33 us
HasFlag
.NET Framework 4.8
.NET Framework 4.8
2,893.10 us
342.563 us
1,010.06 us
2,318.93 us
BitOperator
.NET Framework 4.8
.NET Framework 4.8
38.04 us
3.920 us
11.56 us
30.17 us
So, in .NET Framework 4.8 a HasFlag method was much slower than the BitOperator. But, the performance improves in .Net Core 3.1 and .Net 6.0. So in newer versions, we can use both ways.
Flags are used when an enumerable value represents a collection of
enum members.
here we use bitwise operators, | and &
Example
[Flags]
public enum Sides { Left=0, Right=1, Top=2, Bottom=3 }
Sides leftRight = Sides.Left | Sides.Right;
Console.WriteLine (leftRight);//Left, Right
string stringValue = leftRight.ToString();
Console.WriteLine (stringValue);//Left, Right
Sides s = Sides.Left;
s |= Sides.Right;
Console.WriteLine (s);//Left, Right
s ^= Sides.Right; // Toggles Sides.Right
Console.WriteLine (s); //Left
I'm trying to know if a enum value has defined all flags. The enum is defined as following:
[Flags]
public enum ProgrammingSkills
{
None = 0,
CSharp = 1,
VBNet = 2,
Java = 4,
C = 8,
}
I cannot change the enum to define 'All', because that enum is defined in a dll library.
Of course I can iterate over all enum values, but is there any better/shorter/smarter way to determine if a enum value has defined ALL values?
EDIT:
I would like to have working code even the enum changes.
I don't know if it's better but it is definitely shorter and will work if you modify the enum in the future:
bool result = Enum.GetValues(typeof(ProgrammingSkills))
.Cast<ProgrammingSkills>()
.All(enumValue.HasFlag);
You could do the following:
var hasAll = val == (ProgrammingSkills.CSharp | ProgrammingSkills.VBNet
| ProgrammingSkills.Java | ProgrammingSkills.C);
Or shorter, but not really good for maintenance:
var hasAll = (int)val == 15; // 15 = 1 + 2 + 4 + 8
Or in a generic way:
var hasAll = (int)val == Enum.GetValues(typeof(ProgrammingSkills))
.OfType<ProgrammingSkills>().Sum(v => (int)v);
ProgrammingSkills ps = ProgrammingSkills.None | ProgrammingSkills.CSharp | ProgrammingSkills.VBNet | ProgrammingSkills.Java | ProgrammingSkills.C;
int total = (int)ps;
if (total == 15) return true;//ALL FLAGS THERE
You can test for all members:
bool allSet = value & (ProgrammingSkills.CSharp
| ProgrammingSkills.VBNet
| ProgrammingSkills.Java
| ProgrammingSkills.C) != 0;
The | creates a mask containing all possible values, which is tested (&) against value, containing the enum you want to test.
But that is error-prone and isn't really maintainable. You might want to stick to a loop.
You can cast your enum to int and check if the value than is 15 (sum of all enum-flags):
ProgrammingSkills programmingSkills = ProgrammingSkills.CSharp | ProgrammingSkills.VBNet | ProgrammingSkills.Java | ProgrammingSkills.C;
int programmingSkillsValue = (int)programmingSkills;
if(programmingSkillsValue == 15)
{
// All Flags are set
}
I'm always surprised that even after using C# for all this time now, I still manage to find things I didn't know about...
I've tried searching the internet for this, but using the "~" in a search isn't working for me so well and I didn't find anything on MSDN either (not to say it isn't there)
I saw this snippet of code recently, what does the tilde(~) mean?
/// <summary>
/// Enumerates the ways a customer may purchase goods.
/// </summary>
[Flags]
public enum PurchaseMethod
{
All = ~0,
None = 0,
Cash = 1,
Check = 2,
CreditCard = 4
}
I was a little surprised to see it so I tried to compile it, and it worked... but I still don't know what it means/does. Any help??
~ is the unary one's complement operator -- it flips the bits of its operand.
~0 = 0xFFFFFFFF = -1
in two's complement arithmetic, ~x == -x-1
the ~ operator can be found in pretty much any language that borrowed syntax from C, including Objective-C/C++/C#/Java/Javascript.
I'd think that:
[Flags]
public enum PurchaseMethod
{
None = 0,
Cash = 1,
Check = 2,
CreditCard = 4,
All = Cash | Check | CreditCard
}
Would be a bit more clear.
public enum PurchaseMethod
{
All = ~0, // all bits of All are 1. the ~ operator just inverts bits
None = 0,
Cash = 1,
Check = 2,
CreditCard = 4
}
Because of two complement in C#, ~0 == -1, the number where all bits are 1 in the binary representation.
Its better than the
All = Cash | Check | CreditCard
solution, because if you add another method later, say:
PayPal = 8 ,
you will be already done with the tilde-All, but have to change the all-line with the other. So its less error-prone later.
regards
Just a side note, when you use
All = Cash | Check | CreditCard
you have the added benefit that Cash | Check | CreditCard would evaluate to All and not to another value (-1) that is not equal to all while containing all values.
For example, if you use three check boxes in the UI
[] Cash
[] Check
[] CreditCard
and sum their values, and the user selects them all, you would see All in the resulting enum.
For others who found this question illuminating, I have a quick ~ example to share. The following snippet from the implementation of a paint method, as detailed in this Mono documentation, uses ~ to great effect:
PaintCells (clipBounds,
DataGridViewPaintParts.All & ~DataGridViewPaintParts.SelectionBackground);
Without the ~ operator, the code would probably look something like this:
PaintCells (clipBounds, DataGridViewPaintParts.Background
| DataGridViewPaintParts.Border
| DataGridViewPaintParts.ContentBackground
| DataGridViewPaintParts.ContentForeground
| DataGridViewPaintParts.ErrorIcon
| DataGridViewPaintParts.Focus);
... because the enumeration looks like this:
public enum DataGridViewPaintParts
{
None = 0,
Background = 1,
Border = 2,
ContentBackground = 4,
ContentForeground = 8,
ErrorIcon = 16,
Focus = 32,
SelectionBackground = 64,
All = 127 // which is equal to Background | Border | ... | Focus
}
Notice this enum's similarity to Sean Bright's answer?
I think the most important take away for me is that ~ is the same operator in an enum as it is in a normal line of code.
It's a complement operator,
Here is an article i often refer to for bitwise operators
http://www.blackwasp.co.uk/CSharpLogicalBitwiseOps.aspx
Also msdn uses it in their enums article which demonstrates it use better
http://msdn.microsoft.com/en-us/library/cc138362.aspx
The alternative I personally use, which does the same thing than #Sean Bright's answer but looks better to me, is this one:
[Flags]
public enum PurchaseMethod
{
None = 0,
Cash = 1,
Check = 2,
CreditCard = 4,
PayPal = 8,
BitCoin = 16,
All = Cash + Check + CreditCard + PayPal + BitCoin
}
Notice how the binary nature of those numbers, which are all powers of two, makes the following assertion true: (a + b + c) == (a | b | c). And IMHO, + looks better.
I have done some experimenting with the ~ and find it that it could have pitfalls. Consider this snippet for LINQPad which shows that the All enum value does not behave as expected when all values are ored together.
void Main()
{
StatusFilterEnum x = StatusFilterEnum.Standard | StatusFilterEnum.Saved;
bool isAll = (x & StatusFilterEnum.All) == StatusFilterEnum.All;
//isAll is false but the naive user would expect true
isAll.Dump();
}
[Flags]
public enum StatusFilterEnum {
Standard =0,
Saved =1,
All = ~0
}
Each bit in [Flags] enum means something enabled (1) or disabled (0).
~ operator is used to invert all the bits of the number. Example: 00001001b turns into 11110110b.
So ~0 is used to create the value where all bits are enabled, like 11111111b for 8-bit enum.
Just want to add that for this type of enums it may be more convenient to use bitwise left shift operator, like this:
[Flags]
enum SampleEnum
{
None = 0, // 0000b
First = 1 << 0, // 0001b
Second = 1 << 1, // 0010b
Third = 1 << 2, // 0100b
Fourth = 1 << 3, // 1000b
All = ~0 // 1111b
}