Are there compelling reasons to use a Flags enum (i.e., a bitmask) over a HashSet of regular enums? As far as I can tell, both solve the same problem:
enum Color { Red, Green, Blue }
[Flags()]
enum Colors { None = 0, Red = 1, Green = 2, Blue = 4 }
void Test()
{
// initialization
var supportedColors1 = new HashSet<Color> { Color.Red, Color.Green };
var supportedColors2 = Colors.Red | Colors.Green;
// comparison
if (supportedColors1.Contains(Color.Green)) { /* ... */ }
if ((supportedColors2 & Colors.Green) != 0) { /* ... */ }
// manipulation
supportedColors1.Remove(Color.Red);
supportedColors2 ^= Colors.Red; // if I'm sure that Red is contained
supportedColors2 &= ~Colors.Red; // if I'm not sure
}
It might be a matter of taste, but for someone without a hardware or system-level bit-flipping background (= my co-workers), I would think that the Set option is more readable. I can see the advantage of the Flags option when micro-optimization is required (better performance, less memory) or when P/Invoking the Windows API, but for standard line-of-business database applications I'm tempted to choose the Set option for readability.
Are there some advantages of the Flags option that I have missed and that justify its use in "regular" code?
A flagged enum can be used to efficiently send and store a collection of boolean values. In a flagged enum, each value of the enum is assigned to a bit value. These must be bit values because each combination possible will be unique.
Flags allow an enum value to contain many values. An enum type with the [Flags] attribute can have multiple constant values assigned to it. With Flags, it is still possible to test enums in switches and if-statements. Flags can be removed or added.
Are there some advantages of the Flags option that I have missed
Besides the fact that they are orders of magnitude more efficient? This may not be relevant for you but it’s such an obvious optimisation that it often makes sense.
Furthermore, if you don’t like the bit operation syntax (and I don’t blame you), try defining extension methods to encapsulate them. But I would argue that any competent programmer, no matter their background, absolutely need to know common bit operations anyway. If your coworkers are stumped by this usage, you’ve got big problems.
as you know you can achieve the same with both of them. Using the HashSet will probably be a better choice if you want to store data coming from a database, there will not be any noticeable difference in terms of performances. For sure you will end up with a much more usable (and readable) code and with a type that "fits" better with the data you want to sort out. In both the cases you will iterate or check if a value is present in your container. While the Hashset comes with all the extensions typical for a list (contains, etc..) with the flags you will have to implement these functionalities by yourself (with custom extension methods for instance). The result will be a slowdown in development and less readable code (for your colleagues :) without any type of improvement. Here's a good overview about Enum flags
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With