2

What I have is a string variable that is the name of a enum. I have the integer of the enum. How would I convert that into instance of the enum itself?

Enum TestEnum
    {
        One = 1,
        Two = 2,
        Three = 3
    }

string str = "TestEnum";
int intValue = 2;

I see many posts that require you to have an instance of the enum to get it's like this highly upvoted answer.

I need to do this at runtime.

Edit: I am trying to write a class that gets and sets settings in an api that has hundreds of enums that represent settings.

The enums break are categorized by 5 basic setting types represented by five enums. These enums are like:

DoubleValueEnum
IntegerValueEnum
BooleanValueEnum
StringValueEnum

These enums are pointers to settings of type double, integer, string, bool. I believe that underneath the hood they have a database that keeps a table like this:

Type    key    value      Represents
------- ------ -------    ---------------------------------
Double  23     2.745      DoubleValueEnum.DrawingWidth
Integer 5      18         IntegerValueEnum.PenColor
Double  54     15.9245    DoubleValueEnum.GridMajorSpacing

For doubles there is no "lower" enum that it is pointing to. For integer there is a deeper enum like "PenNumber.Red = 1, PenColor.Green = 2.

Hypothetical pen color:

Enum PenColor
{
    Red = 1,
    Blue = 2,
}

Each of these enums have hundreds of values. Each of these enums has a prewritten function the gets or sets the enum:

GetDoubleEnumValue(int, option)
GetIntegerValueEnum(int, option)
GetBooleanValueEnum(int, option)
GetStringValueEnum(int, option)

SetXXXXXEnumValue(enum, value)
SetDoubleEnumValue(int, int)
SetIntegerValueEnum(int, int)
SetBooleanValueEnum(int, int)
SetStringValueEnum(int, int)

Real example:

SetIntegerValueEnum ((int)IntegerValueEnum.swDxfVersion, (int)swDxfFormat_e.swDxfFormat_R14);
Eric Snyder
  • 1,816
  • 3
  • 22
  • 46
  • 3
    This could be an XY problem. Can you provide more detail about what you're trying to accomplish by doing this? (Less about the mechanism, more about the goal.) – madreflection Feb 21 '20 at 23:52
  • 1
    While this is surely possible using reflection, there are problems. E.g. what if more then a single enum-value map to the exact same number. This is absolutely valid. – MakePeaceGreatAgain Feb 22 '20 at 00:08
  • But even then all you ever get is some un-generic insance of `Enum`, which essentialy is just the actual number. So there´s no real benefit in doing that at runtime. – MakePeaceGreatAgain Feb 22 '20 at 00:12
  • Are you suggesting that you don't have a definition of the enum available? or do you want to cast one enum to the equivalent string value of another enum? – Chris Schaller Feb 22 '20 at 00:12
  • How do you have a "double" enum? Or really, anything other than an Integer enum? An enum can only be be based on one of 8 *integral* types. – madreflection Feb 22 '20 at 00:19
  • So how does `SetIntegerValueEnum` look like? And where is the string provided here? – MakePeaceGreatAgain Feb 22 '20 at 00:21
  • @madreflection - A "Double" enum is representing a double type setting in the API. It is were the width of a line it might be "DoubleValueEnum.LineWidth". That enum value represents a setting that has the value of double (a line with could be a real number between 0.01mm - 10mm for instance). Thus a "DoubleEnum". – Eric Snyder Feb 22 '20 at 00:24
  • So the enum specifies which setting it is, like an identifier, not the value of a setting. Is that correct? Partitioning settings into enums by data type may be an unnecessarily imposed limitation. – madreflection Feb 22 '20 at 00:25
  • We're all thuinking this, not sure enum is the right mechanism to use for this... however, can you please post the partial defintion of the enums, and an example value that you want to parse – Chris Schaller Feb 22 '20 at 00:33
  • Are you just trying to bitwise _and_ the enum values together? – Chris Schaller Feb 22 '20 at 00:36
  • @madreflection - Correct. Enums specify the setting. Some enums are single level. DoubleValueEnum.LineWidth just points to the setting. The rest of the enums are two level - IntegerValueEnum.PenColor actually points to another enum - PenColor.Red. – Eric Snyder Feb 22 '20 at 00:37
  • @ChrisSchaller - Unfortunately, the enum structure that the API has is what I have to work with. :( I don't like it but the API was released in 1995 and it is clear that it has grown every year with each new release. I am certain they would do things completely different today. – Eric Snyder Feb 22 '20 at 00:40
  • In that case, I might design an alternative API that I think would be easier to use, and then maybe code-gen a facade over the enums. But that's just me. – madreflection Feb 22 '20 at 00:43
  • @madreflection - Not sure what you mean??? – Eric Snyder Feb 22 '20 at 00:45
  • Can you post the full definition of PenColor enum – Chris Schaller Feb 22 '20 at 00:47
  • There's not much to tell. It's an abstract idea because I still haven't seen enough of what you're dealing with to be sure it would even work, or be any better if it did. – madreflection Feb 22 '20 at 00:48
  • Is this a public API that we can access, enums used like this is usually to make the process simpler, or more efficient, I'd like to help you here but we need to see some of the enum definitions to finish painting the picture. I'm sure that `PenColor` has more than two values... – Chris Schaller Feb 22 '20 at 01:49

2 Answers2

0

For your given enum definition:

enum TestEnum
{
    One = 1,
    Two = 2,
    Three = 3
}

enum TestEnum2
{
    OnePoint1 = 1,
    OnePoint2 = 2,
    OnePoint3 = 3
}

Use Enum.Parse(Type, string) to parse the string value as an Enum value.

string str = "Two";
TestEnum valueAsEnum = (TestEnum)Enum.Parse(typeof(TestEnum), str);

However, you need to know they type of the Enum definition that you want to parse. If the exact type of the enum value is unknown, but you do know the potential types, then you can iterate through the types and test using the Enum.TryParse

string str = "Two";
object enumValue = null;

if (!Enum.TryParse(typeof(TestEnum), str, true, out enumValue))
    Enum.TryParse(typeof(TestEnum2), str, true, out enumValue))

If you do not know the specific type of the enum but you do know the class name, you can use the Type.GetType Method to resolve the type

For this to work you do need to know the full namespace of type that you want to resolve, AND the assembly that the type is defined in must already be loaded.

The syntax to convert an int to an enum is discussed here: https://stackoverflow.com/a/56859286/1690217

In this example, we know that all of the enums reside in the API.Client.Enums namespace:

string str = "TestEnum";
int intValue = 2;

string ns = "API.Client.Enums";
Type enumType = Type.GetType($"{ns}.{str}");

// now we can parse the value:
object value = Enum.ToObject(enumType, (object)intValue);

Usually we do not need to bother with a lot of this conversion just to pass values between systems, the fact that the enum resolves to an integer means that for unknown types we should be able to write our logic to just deal with the integer, and only convert it back to a specific enum when you need it.

Chris Schaller
  • 13,704
  • 3
  • 43
  • 81
  • 1
    casting to `TestEnum` assumes OP knows the exact type at compile-time which he apparently does not. Apart from this your answer is exactly the same as that one from the link mentioned in OPs question. – MakePeaceGreatAgain Feb 22 '20 at 00:11
0

It looks like you are trying to use BitWise operations on Enum values to allow a single setting property to represent multiple optional states.

For this sir Enums have support built in if you use the Flags attribute:
There is a good SO dicussion that covers this too: What does the [Flags] Enum Attribute mean in C#?

Lets look at PenColor enum first:

[Flag]
enum PenColor : int
{
    None = 0        // 0
    Red = 1 << 0,   // 1
    Green = 1 << 1, // 2
    Blue = 1 << 2   // 4
}

By defining the discrete enums with base-2 values, we can now use either bitwise operations on the PenColor enum, or we can use simple integer addition/subtraction:

PenColor cyan = PenColor.Green | PenColor.Blue;
int cyanInt = (int)PenColor.Green + (int)PenColor.Blue;
PenColor cyanCasted = (PenColor)cyanInt;

All of those statements will be equivalent. So potentially this syntax replaces your SetIntegerValueEnum, but it relies on the enum definition being implemented with base-2 values.

To test, this statement should be true:

SetIntegerValueEnum ((int)IntegerValueEnum.swDxfVersion, (int)swDxfFormat_e.swDxfFormat_R14)  
== (int)IntegerValueEnum.swDxfVersion + (int)swDxfFormat_e.swDxfFormat_R14)  
== IntegerValueEnum.swDxfVersion | swDxfFormat_e.swDxfFormat_R14

The last option will only work if the [Flags] attribute decorates the enum type definition.

You can then use this in switching logic or comparisons

PenColor cyan = PenColor.Green | PenColor.Blue;
bool hasBlue = cyan & PenColor.Blue == PenColor.Blue;
// you can also use the slower Enum.HasFlag
hasBlue = cyan.HasFlag(PenColor.Blue);
Chris Schaller
  • 13,704
  • 3
  • 43
  • 81