Do enums need an index? - c#

I have a number of enums that contain long lists that do change from time to time
public MyEnumType MyEnum
{
None = 0,
Option1 = 1,
Option2 = 2,
etc..
}
When they change, I need to renumber the index as invariably new options are placed inbetween existing options.
The question is, if I remove the index, will the enum always honour the order from top to bottom?
public MyEnumType MyEnum
{
None,
Option1,
Option2,
etc..
}
Thanks in advance.

Yes they will.
You can also specify just the first element if you want to make sure that values start at some specific value:
public MyEnumType MyEnum
{
None = 1,
Option1, // -> 2
Option2, // -> 3
}
For other details, check the docs.
Note that in most scenarios, your code should not care about the exact numeric values.
Situations when you do care are e.g. if you declare an enum which is an alias for an external type (e.g interop) so you need to ensure that values are the same. Another scenario is when the enumeration represents binary flags, then you want something like:
[Flags]
public MyEnumType MyEnum
{
None = 1,
Option1 = 2,
Option2 = 4
}

Simplest answer would be "Yes"... they will always honor the order.
So you no need to put index number.
public MyEnumType MyEnum
{
None,
OptionA,
OptionB,
OptionC,
...
...
OptionZ
}
this will always same as -
public MyEnumType MyEnum
{
None = 0,
OptionA = 1,
OptionB = 2,
OptionC = 3,
...
...
OptionZ = 26
}
If you introduce new enum type in between like -
public MyEnumType MyEnum
{
None,
OptionA,
OptionB,
OptionC,
...
...
OptionO
OptionNew
OptionP
...
...
OptionZ
}
Then above will be equivalent to -
public MyEnumType MyEnum
{
None = 0,
OptionA = 1,
OptionB = 2,
OptionC = 3,
...
...
OptionO = 15
OptionNew = 16
OptionP = 17
...
...
OptionZ = 27
}

Yes they honour the order, starting from the default value for int, which is zero.
If you are regularly renumbering things then it is better to explicitly assign values to the enum members, and then re-number the items when the underlying list that it is based on changes.
If you use explicit numbering then you can also insert new items into the list between existing items at any time, although you do need to be careful that you don't assign two items to the same value (which is totally legal in C#, but may produce errors if you didn't intend it).

From the C# language specification 1.10 Enums:
... When an enum member declaration does not explicitly specify a value,
the member is given the value zero (if it is the first member in the
enum type) or the value of the textually preceding enum member plus
one.
So the same as your explicit declaration here:
public MyEnumType MyEnum
{
None = 0,
Option1 = 1,
Option2 = 2,
etc..
}

By default they will count up from zero in the order they are declared.
If you define one explicitly, then the subsequent values continue counting up, using the explicit value as a seed.

Related

Is there a type that is the opposite of an enum?

For example, here is a simple enum:
enum Something {
One = 1,
Two = 2,
Three = 3
}
But I would like to create the opposite of this code, like
SomeType Something {
1 = One,
2 = Two,
3 = Threee
}
Maybe I could introduce constants, like
static class Something {
public const 1 = "One";
// ...
}
but I get compiler errors (CS1031, CS1001, CS0145 and CS1003), because c# can't handle this.
I can do the same with enums to prevent these unnecessary errors, but here I also get CS1001, because c# does not undertand that the numbers are the identifiers.
I can also use strings, but this makes it even more complicated, because c# expects another identifier for them (but doesn't accept one (CS0029))
So, is there anything in c# that can be used to assign some string-like values to numbers as constants or like enums?
You can not have numeric value as your variable name, So to solve this issue you can create a Dictionary of key integer and value as string like this Dictionary<int, string> and use it accordingly.
If that's how to use the enum name, you can use Enum.TryParse<someEnumTyme>(someString, out _someEnumVar).
But the Dictionary solution of is more elegant in my opinion.
At runtime, for many operations, using an enum variable is the same as using the underlying type.
enum Something {
One = 1,
Two = 2,
Three = 3
}
Something foo = Something.One; // assign 1 to foo
You can use the definition of an enum to create a mapping between values and names;
var lookup = ((Something[])Enum.GetValues(typeof(Something)))
.ToDictionary(e => e.ToString(), e => (int)e);

What is the difference between local defined Enum-flags and Enum-defined flags?

I was working with Enums and I was looking for a way to group a range of enum-values to separate groups when I came across [Flags] for Enums.
I noticed that the example on ms-Docs was printing the array of the local declared enum bit-wise range (as the enum names) but not when I declared the same range in the enum itself.
I have tested the Enum.HasFlag() and it does the same calculation, but it does not print it in the same way. I have found plenty of solutions for flag iterators, but it seems that the feature is there already for local declared variables.
What is the difference between the enum declared value and the local declared enum?
[Flags]
public enum DinnerItems
{
None = 0,
Entree = 1,
Appetizer = 2,
Side = 4,
Dessert = 8,
Beverage = 16,
BarBeverage = 32,
MyOrder = Appetizer | Entree | Beverage | Dessert,
}
DinnerItems flagValue = DinnerItems.None | DinnerItems.Side;
DinnerItems myOrder = DinnerItems.Appetizer | DinnerItems.Entree |
DinnerItems.Beverage | DinnerItems.Dessert;
Console.WriteLine("{0} includes {1}: {2}",
myOrder, flagValue, myOrder.HasFlag(flagValue));
This will print:
MyOrder includes Side: False
Same code when removing DinnerItems.MyOrder from Enum:
Entree, Appetizer, Dessert, Beverage includes Side: False
As per the docs:
The return value is formatted with the general format specifier ("G").
That is, if the FlagsAttribute is not applied to this enumerated type
and there is a named constant equal to the value of this instance,
then the return value is a string containing the name of the constant.
If the FlagsAttribute is applied and there is a combination of one or
more named constants equal to the value of this instance, then the
return value is a string containing a delimiter-separated list of the
names of the constants.
Without MyOrder, it thus does the delimiter-separated list of the names - which appears to be what you want.
But with MyOrder - well now MyOrder is the simplest combination of one or more named constants (one constant, vs four) - so it outputs MyOrder instead.

How to get values of combined bitwise

I have types that have a bitwise value [1,2,4,8,16,32] that are selected from checkboxes, when saving to the database i combine the selected values and get a value of 42 for instance. How can i calculate which values were selected from the combined value, on an edit screen i want to recheck the values that were selected.
To check whether e.g. 8 is contained in your combined value, you can use the bitwise and operator like this:
int combinedValue = 42;
int bitwiseValue = 8;
bool isBitwiseValueChecked = (combinedValue & bitwiseValue) == bitwiseValue;
Use an enum to model the flags:
public static void Main()
{
Console.WriteLine((MyFlags)1); // Foo
Console.WriteLine((MyFlags)7); // Foo, Bar, Baz
Console.WriteLine((int)(MyFlags.Foo | MyFlags.Bar)); // 3
}
[Flags]
enum MyFlags
{
Foo = 1,
Bar = 2,
Baz = 4
}
Then, to list all members, see List all bit names from a flag Enum

How to sort my list object based on order of Enum values

I have an enum:
public enum EnumProductConfig
{
Color,
Fold,
Edge,
Hem,
Lift,
Tapes,
Control,
Clips,
Pull,
Val
}
The order of above values in enum is not alphabatical which is totally ok with me.
Now, I have a list with one of the property of type EnumProductConfig. I want to sort my list based on that property (which is of Enum type) in the order of appearance in the Enum. I do not want to sort it alphabetically. The order must stay as mentioned in my Enum. Hence all rows with value Color must come first. Followed by Fold etc.
Please advise.
myData.OrderBy(d => (int)d.ProductConfig).ToList();
Should do it. Import System.Linq
Enums are really just ints anyway, going from zero and increasing by 1. You can also give each value a specific int value if you want to.
Also, you should not prefix your enum type with the word enum as it is against the Microsoft naming guidelines.
In c#, an enum is a group of numeric value constants.
If not specified, the enum's underlying type is int:
Every enumeration type has an underlying type, which can be any integral type except char. The default underlying type of enumeration elements is int
And every enum member gets a value from 0 to n, where n is the number of members -1:
By default, the first enumerator has the value 0, and the value of each successive enumerator is increased by 1.
Since you didn't specify neither the underlying type nor the values, your enum is equivalent to:
public enum EnumProductConfig : int
{
Color = 0,
Fold = 1,
Edge = 2,
Hem = 3,
Lift = 4,
Tapes = 5,
Control = 6,
Clips = 7,
Pull = 8,
Val = 9
}
This means you can simply order by your EnumProductConfig property:
var list = new List<MyClass>()
var sorted = list.OrderBy(c => c.ProductConfig);
You can see a live demo on rextester.

Convert CSV from enum flags and vice versa

Consider the following enum:
[Flags]
public enum MyEnum
{
Option1 = 0,
Option2 = 1,
Option3 = 2,
Option4 = 4
}
Is there a way in which I can get the string equivalent (not the value) as a CSV string? Normally I can use the Enum.GetName function to convert a type to the string representation, however, if you use a combination this returns null.
So basically I would like to convert:
var options = MyEnum.Option1 | MyEnum.Option3;
into
"Option1, Option3"
Then I would like to be able to convert "Option1, Option3" back to MyEnum.Option1 | MyEnum.Option2.
Suggestions?
Well, aside from Option1 not making much sense in a flags enum, this just works by default using Enum.Parse and Enum.ToString().
Start with this:
var options = MyEnum.Option2 | MyEnum.Option3;
Console.WriteLine(options.ToString());
// Outputs: Option2, Option3
Then you can always do this:
var options2 = (MyEnum) Enum.Parse(typeof (MyEnum), "Option2, Option3");
Now try this:
Console.WriteLine((options2 & MyEnum.Option2) == MyEnum.Option2);
Console.WriteLine((options2 & MyEnum.Option4) == MyEnum.Option4);
// Outputs:
// true
// false
Which seems like it does exactly what you wanted (again, ignoring the fact that Option1 in your example will never occur)
docs: Enum.Parse
You could do a Enum.GetValues which gets an array of enum values. You can then loop through those values and test them against your Enum value, concatenating the string value for each one that matches. The other way around you can loop through the values using the Enum.GetName function to test if your string contains that values name and then rebuild the value.

Categories

Resources