Convert CSV from enum flags and vice versa - c#

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.

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);

Do enums need an index?

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.

Return Enum Constant based on an incoming String Value

I'm going to grab the enum value from a querystring.
For instance lets say I have this enum:
Enum MyEnum
{
Test1,
Test2,
Test3
}
I'm going to grab the value from an incoming querystring, so:
string myEnumStringValue = Request["somevar"];
myEnumStringValue could be "0", "1", "2"
I need to get back the actual Enum Constant based on that string value.
I could go and create a method that takes in the string and then perform a case statement
case "0":
return MyEnum.Test1;
break;
but there's got to be an easier or more slick way to do this?
Take a look at Enum.Parse, which can convert names or values to the correct enum value.
Once you have that, cast the result to MyEnum and call ToString() to get the name of the constant.
return ((MyEnum)Enum.Parse(typeof(MyEnum), Request["somevar"])).ToString();
There is built-in functionality for this task:
MyEnum convertedEnum = (MyEnum) Enum.Parse(typeof(MyEnum), myEnumStringValue);
You need to parse the string to get its integer value, cast the value to the Enum type, then get the enum value's name, like this:
string myEnumStringValue = ((MyEnum)int.Parse(Request["somevar"])).ToString();
EDIT: Or, you can simply call Enum.Parse. However, this should be a little bit faster.

Possible to load an Enum based on a string name?

OK, I don't think the title says it right... but here goes:
I have a class with about 40 Enums in it. i.e:
Class Hoohoo
{
public enum aaa : short
{
a = 0,
b = 3
}
public enum bbb : short
{
a = 0,
b = 3
}
public enum ccc : short
{
a = 0,
b = 3
}
}
Now say I have a Dictionary of strings and values, and each string is the name of above mentioned enums:
Dictionary<string,short>{"aaa":0,"bbb":3,"ccc":0}
I need to change "aaa" into HooBoo.aaa to look up 0. Can't seem to find a way to do this since the enum is static. Otherwise I'll have to write a method for each enum to tie the string to it. I can do that but thats mucho code to write.
Thanks,
Cooter
You'll have to use Reflection to get the underlying enum type:
Type t = typeof(Hoohoo);
Type enumType = t.GetNestedType("aaa");
string enumName = Enum.GetName(enumType, 0);
If you want to get the actual enum value, you can then use:
var enumValue = Enum.Parse(enumName, enumType);
Use
aaa myEnum =(aaa) Enum.Parse(typeof(aaa), "a");
You want to convert a string -> enum? This should help.
Just keep in mind that Enum.Parse isn't strongly typed... I reckon that will be a real limitation in your scenario. As you can see from Ngu's example you'd have to cast the output.

Why does enum.ToString() give a different result than what's shown in the debugger tooltip?

Test program (.NET 2.0):
[Flags]
enum MyEnum
{
Member1 = 1,
Member2 = 2,
}
class Program
{
// Inspecting r shows "Member1 | Member2"
MyEnum r = MyEnum.Member1 | MyEnum.Member2;
// s = "Member1, Member2"
string s = r.ToString();
}
I would have expected .ToString() to return a string with the members separated by a pipe, but that's not the case.
Bonus info: calling Enum.Parse() on the comma-separated string succeeds, while supplying it with a pipe-separated string fails.
The VS debugger uses visualizers to display values. Only if there's no visualizer for a specific datatype, it will fallback to the .ToString() method.
More info on visualizers:
http://msdn.microsoft.com/en-us/library/zayyhzts.aspx
The default ToString implementation for an enum marked with FlagsAttribute is a comma-separated list. However, it is not necessarily the ToString result that is shown in the debugger - there must be a Debugger Visualizer set up for enums that renders the values with the bitwise OR symbol or pipe.

Categories

Resources