-3

By default, if no Enum value are assigned, they are automatically assigned by the compiler with a zero-based index:

[Flags]
public enum MyColors
{
    Yellow,  // 0
    Green,   // 1
    Red,     // 2
    Blue     // 3
}

Assigning binary values to the Enum members allows doing bitwise operations, and they can be assigned by sequencing values in orders of magnitude of 2:

[Flags]
public enum MyColors
{
    Yellow = 1,
    Green  = 2,
    Red    = 4,
    Blue   = 8
}

or, more conveniently, make bitwise shifts:

[Flags]
public enum MyColors
{
    Yellow = 0,
    Green  = 0 << 0,
    Red    = 0 << 1,
    Blue   = 0 << 2
}

But what if I now want to add Orange to this list between Yellow and Green, while keeping the value numbering nice and consistent? This is the intended result:

[Flags]
public enum MyColors
{
    Yellow = 0,
    Orange = 0 << 0
    Green  = 0 << 1,
    Red    = 0 << 2,
    Blue   = 0 << 3
}

As you can see, I had to manually edit the shift operations after Orange to keep the numbering nice and consistent. This can quickly become cumbersome with very large Enums. This is not Microsoft Word where you can insert a new item into a numbered list and have the list numbering update automatically after the inserted item. But this kind of feature would be very nice to have.

The problem arises from having to specify the Enum values to binary sequence manually, because by default the Enum members are numbered in decimal.

So, my question is, is it possible to change this default compiler behavior to assign values to Enum members using binary sequence logic, instead of the default decimal one? I am coding with Visual Studio in case that matters.

Disclaimer: I am fully aware that the order of items in Enum doesn't really matter in most cases, nor does the assignment of the member values, meaning I could insert Orange at the bottom and skip having to edit the rest of the member values, or insert Orange where I want, and have a bit messed up numbering sequence. But in certain cases it kind of matters where the newly inserted member is (for example, when printing the Enum member names through reflection), and having the value numbering without any order makes it difficult to determining the value in sequence for a new member. That is why I want to skip having to specify these binary values altogether, and have compiler assign them automatically.

  • 3
    Just a tip: you want it to be `1 << 0`, `1 << 1`, etc, not 0. – Dennis_E Dec 06 '20 at 21:06
  • 2
    It's actually bad practice to keep adding enum values/flags in between others and renumber the others. It breaks the interface and might cause version incompatibilities in your api. Or serialized configuration files that don't work anymore. Just some examples – JHBonarius Dec 06 '20 at 21:35
  • I agree with @JHBonarius. If your enums are changing frequently enough that this becomes a significant problem, you'll probably run into bigger problems down the line, and you should probably consider approaches that don't involve enums. – BenM Dec 06 '20 at 22:00
  • Indeed: `0 << X = 0`... You need to use `1 << X` where `X` is `0, 1, 2, 3, 4, 5...`. `0` being *None*, no value set. And when you need to add a value, you add it at the end of the list with the next value or any available if you don't use a continuous series. Otherwise personnaly, when having lots of values, I prefer using bitwise shift that is simpler and that reduces the source of errors. –  Dec 06 '20 at 22:06
  • Found that: https://stackoverflow.com/questions/10558621/any-trick-to-defining-an-enum-as-flags-powers-of-2-without-eventually-needing-a : with C# 7 you can use binary literals instead of shifts like `0b00000001` and `0b00000010`, so you can *draw* your enums like an old 80's program. –  Dec 06 '20 at 22:14
  • _"is it possible to change this default compiler behavior"_ -- no. See first duplicate. There are a number of good, practical work-arounds. See second duplicate. – Peter Duniho Dec 06 '20 at 22:49
  • Please re-open the question. The so called duplicates DO NOT answer my question, and the workarounds are not applicable. I have read these two questions, among many other questions, and none of them provided a solution. Please re-open my question so that someone might come along and suggest a compiler settings modification that I am looking for. – Justinas Rubinovas Dec 06 '20 at 23:32
  • There are no compiler settings modifications that will do what you want. Just as the first duplicate explains. There is no reason whatsoever to reopen this question; it's been thoroughly addressed already on Stack Overflow. – Peter Duniho Dec 07 '20 at 00:43
  • In that first "duplicate" the most upvoted answer just repeats what I already addressed in my question - that BY DEFAULT, enum values are assigned in a decimal sequence, and if one wants to use bitwise operations for enums, binary sequence should be specified for enum values. Again, I clearly stated that I know this at the beginning of my question. What I asked was for some way to have binary sequence assigned by default, so that I wouldn't have to explicitly write it for every member of enum. That other asker was just looking for confirmation of usual method; I am looking for alternative. – Justinas Rubinovas Dec 07 '20 at 00:52
  • The answer is: "no". But you should be able to make your own VS Addon if you have any ideas on how to do it according to your needs. But before you need to figure out what enum flags are because your question contains misconception errors (see my previous comment and those of others as well as the @MateuszGiedziński's answer): https://learn.microsoft.com/dotnet/api/system.flagsattribute –  Dec 07 '20 at 08:35

2 Answers2

1

Maybe this extensions for visual studio can help you. https://marketplace.visualstudio.com/items?itemName=VictorCherniavsky.EnumComposerVSIX Based on documentation it generate enum using specified database query. So you can manage yours flags in dedicated database table and then regenerate enum before build.

Another option is set flag values as binary literals

[Flags]
public enum MyColors
{
    None   = 0b000000,
    Green  = 0b000001,
    Red    = 0b000010,
    Blue   = 0b000100,
    Yellow = 0b001000,
}

For checking for duplicates I suggests using some analyzer for example Roslynator.

-2

The answer is simple: No, it's not possible to change the behaviour of the C# compiler in this way

Orion Edwards
  • 121,657
  • 64
  • 239
  • 328