Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flags enum vs. HashSet of regular enum

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?

like image 634
Heinzi Avatar asked Jan 31 '12 09:01

Heinzi


People also ask

What is a flagged enum?

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.

What does the flags attribute enable for an enum?

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.


2 Answers

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.

like image 119
Konrad Rudolph Avatar answered Oct 20 '22 00:10

Konrad Rudolph


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

like image 41
Giorgio Minardi Avatar answered Oct 20 '22 00:10

Giorgio Minardi