0

This is my enum:

public enum Colors
        {
            Dark Green = 0,
            Light Green = 0,
            Red = 1,
            Orange = 1,
            Yellow = 1,
            Blue = 2,
            Light Blue = 2,
            Black = 2
       }

I have the value 1, and want to get the first element with this value [Red]. I tried this:

Colors c = (Colors)(Enum.GetValues(typeof(Colors))).GetValue(1);

or this:

Colors c = (Colors)1;

But both returns the middle value - orange. Is there a way to get the first element? Appreciate a response.

dasi
  • 11
  • 1
  • Please use different values or consider using a flag enumerator. – MatteoCracco97 Aug 25 '20 at 06:22
  • You cannot use the same values on items, and you cannot have spaces in keys/names. – Svein Terje Gaup Aug 25 '20 at 06:34
  • 1
    [Can you have multiple enum values for the same integer?](https://stackoverflow.com/questions/15458101/can-you-have-multiple-enum-values-for-the-same-integer) – Tân Aug 25 '20 at 06:38
  • [GetName for enum with duplicate values](https://stackoverflow.com/questions/9754604/getname-for-enum-with-duplicate-values) – Tân Aug 25 '20 at 06:38
  • [Get values of an enum variable having duplicate values with different keys](https://stackoverflow.com/questions/36623501/get-values-of-an-enum-variable-having-duplicate-values-with-different-keys/36623978) – Tân Aug 25 '20 at 06:39
  • Hi @dasi! Do you have to use an enum? I would recommend a better suited data structure like a dictionary and use some linq to perform the lookup. – Zorgarath Aug 25 '20 at 07:18
  • regarding the spaces - this is a dummy code, so I didn't notice to that... the original enum doesn't contain spaces. and yes, I do need to use enum, most use-cases I use are like an `enum`, and have an interest to same values for several elements. only in once case I would like to refer to the first element by the level. I would prefer to not use an additional data structure like dictionary for that, and tried to find out if there is an option to do so... – dasi Aug 25 '20 at 10:03

3 Answers3

3

If you actually need different colors to map onto the same integer, I suggest you need a different data structure, one that allows mapping, like a dictionary.

enum Colors { DarkGreen, LightGreen, Red, Orange, Yellow, Blue, LightBlue, Black };

var lookup = new Dictionary<Colors,int>
{
    { DarkGreen, 0 },
    { LightGreen, 0 },
    { Red, 1 },
    { Orange, 1 }
    ///etc
};

Now your colors are truly unique, and to find the first element of a given value you can then do:

lookup.FirstOrDefault(x => x.Value == lookupValue);

but whenever you need the integer value, you can just look it up:

var colorIndex = lookup[Colors.Red];
Zorgarath
  • 979
  • 12
  • 23
John Wu
  • 50,556
  • 8
  • 44
  • 80
  • dasi would like to get a color by the first match of its value, which can be done like so: `lookup.FirstOrDefault(x => x.Value == lookupValue);` – Zorgarath Aug 25 '20 at 07:15
0

It's (in general with some specific exceptions) bad idea to have multiple members of enum with the same value. Why don't you do

public enum Colors
    {
        Dark Green = 1,
        Light Green = 2,
        Red = 3,
        Orange = 4,
        Yellow = 5,
        Blue = 6,
        Light Blue = 7,
        Black = 8
   }

?

0

But both returns the middle value - orange"

To clarify: in your enum, Red, Yellow and Orange are exactly the same thing; enums in .NET are simply integers - the name part only applies when:

  • writing code
  • when parsing a string into an enum value at runtime
  • when formatting an enum value to a string at runtime

The order of members (including enum definitions) is explicitly not defined in .NET, so all we have a bunch of integer/name pairs - but conceptually, once you have the enum: it is just an integer, and 1 is 1 is 1, regardless of whether you were originally thinking of Red, Yellow, or Orange. In terms of which will be used when performing string parse/format operations when an enum is overlapped like this: again, that is largely undefined, but you can figure it out with trial and error as long as you acknowledge that this is open to change without warning.

Ultimately, don't do this. Either use different values for each enum member, or use a different metaphor to express your intent here. Perhaps what you really want here is something more like:

public enum Colors
{
    [SomeMarker(0)]
    DarkGreen, // = 0 implicitly
    [SomeMarker(0)]
    LightGreen, // = 1 implicitly
    [SomeMarker(1)]
    Red, // = 2 implicitly
    [SomeMarker(1)]
    Orange, // = 3 implicitly
    [SomeMarker(1)]
    Yellow, // = 4 implicitly
    [SomeMarker(2)]
    Blue, // = 5 implicitly
    [SomeMarker(2)]
    LightBlue, // = 6 implicitly
    [SomeMarker(2)]
    Black, // = 7 implicitly
}

Looking up custom attribute values from enums is perfectly possible. So you'd just define your SomeMarkerAttribute : Attribute.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900