considering the following enum:
public enum LeadStatus
{
Cold = 1,
Warm = 2,
Hot = 3,
Quote = 5,
Convert = 6
}
How can I convert the integer value back to string when I pull the value from a database. I've tried:
DomainModel.LeadStatus status = (DomainModel.LeadStatus)Model.Status;
but all I seem to get is "status = 0"
What you are looking for is Enum.Parse.
"Converts the string representation of the name or numeric value of one or more enumerated constants to an equivalent enumerated object."
Here is the MSDN page: http://msdn.microsoft.com/en-us/library/essfb559.aspx
Example:
enum Colour
{
Red,
Green,
Blue
}
// ...
Colour c = (Colour) Enum.Parse(typeof(Colour), "Red", true);
Courtesy of http://blogs.msdn.com/tims/archive/2004/04/02/106310.aspx
Between Enum.Parse and Enum.ToString, you should be able to do everything you need.
Given "Model.Status" is the integer from the database, it can be restored to the Enum string value with:
string status = Enum.GetName(typeof(DomainModel.LeadStatus), Model.Status);
Just use ToString() on the enum object
An enumeration in C# is used to provide names for some known values but ANY integer value is permissible in that enumeration, whether it has a named equivalent or not.
In your example, you have not named a zero value, but your status variable initialises to zero. I suspect that it has not changed from this initial value at the point you read it. Therefore, it's string representation is also 0 and you will parse out zero when you parse it.
Related
This question already has answers here:
Create instance of unknown Enum with string value using reflection in C#
(2 answers)
Closed 3 years ago.
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);
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.
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);
I need to convert a List of enums values to a single string to store in my db; then convert back again when I retrieve from the database.
Each enum's value is currently a simple integer, so it feels a bit overkill to create an extra table to deal with this.
So, in the example below, if the user selects Mother, Father and Sister, then the value stored in the database will be "0,1,3"
public enum MyEnum
{
Mother = 0,
Father = 1,
Gran = 2,
Sister = 3,
Brother = 4
}
I'm new to c#, so not sure if there is a nice out-the-box way to do this - I couldn't find anything obvious when google hunting!
Cheers in advance :)
- L
Enum's are explicitely able to be cast to/from integers
int value = (int)MyEnum.Mother;
and
MyEnum value = (MyEnum)1;
For strings use ToString and Enum.Parse
string value = MyEnum.Mother.ToString();
and
MyEnum value = (MyEnum)Enum.Parse(typeof(MyEnum),"Mother");
If you change you enum values to:
[Flags]
public enum MyEnum
{
Mother = 1,
Father = 2,
Gran = 4,
Sister = 8,
Brother = 16,
}
Then you could store Father and Gran as 6
Sister and Brother as 24 etc
by using binary numbers you should not get duplicate values by combining them
The following will convert back and forth between an array of Enum values via "0,1,3" as requested:
MyEnum[] selection = { MyEnum.Mother, MyEnum.Father, MyEnum.Sister };
string str = string.Join(",", selection.Cast<int>());
MyEnum[] enm = str.Split(',').Select(s => int.Parse(s)).Cast<MyEnum>().ToArray();
from your code it is
MyEnum a = MyEnum.Mother;
string thestring = a.ToString();
MyEnum b = (MyEnum) Enum.Parse(typeof(MyEnum), thestring);
Just use ToString to convert to the name, and the use Enum.TryParse (or Enum.Parse if you're not on .NET 4) to convert back.
If you're wanting one enum field to contain multiple values (e.g MyEnum.Mother | MyEnum.Father), you'll need to convert that to a Flags enum, as #WraithNath suggested. Otherwise you're talking about storing each option separately (there's no way to store Mother and Father in the same field with your current setup).
String Equivelant
MyEnum value = MyEnum.Father;
value.ToString(); // prints Father
Parsing
(MyEnum)Enum.Parse(typeof(MyEnum), "Father"); // returns MyEnum.Father
Enums can be cast to and from integer values. That's probably your best bet.
If you really want to use strings, ToString will return "Mother" "Father" "Gran" etc. Casting back from a string would just be a function:
private MyEnum GetEnumValue(string fromDB)
{
if( fromDB == "Mother" ) return MyEnum.Mother;
else if( fromDB == "Father") return MyEnum.Father;
//etc. etc.
}
EDIT:
Ian's answer for casting back is the more "C#-ey" way of doing it, and is far more extensible (handles adding new values to the enum much more flexibly).
Further to Jamiec's suggestion (which fits well for your need), if you need to defensively code your casting, try:
if (Enum.IsDefined(typeof(MyEnum), <your database value>))
{
// Safe to convert your enumeration at this point:
MyEnum value = (MyEnum)1;
}
Okay, for whatever reason I can't seem to figure this little problem out.
I have the following enum:
public enum EFeedType
{
TypeOne = 1,
TypeTwo = 2
}
Now, I am going to be getting the numeric value from a database. Well, I need to cast the int value from the DB to the enum type:
EDIT:
The database type is integer, so I do not need to cast from string.
END EDIT
EFeedType feedType = (EFeedType) feedId;
However, when I do this, and pass in value of 2 I get the following error:
Instance validation error: '2' is not a valid value for [Namespace Goes Here].EFeedType.
Any thoughts on what I might be doing wrong or missing?
EDIT
Here is the code I am using:
//GetFeed will return an int value which is pulled from the database
int feedId = new FeedEngine().GetFeed("FeedName");
//Convert the ID to the Enum
EFeedType feedType = (EFeedType) feedId;
//Set the User Control FeedType Enum to the enum
FeedControl.FeedType = feedType;
//Show the user control
FeedControl.Visible = true;
EDIT - More Info
Okay, after seeing JSkeet's response, I see that If my feedId = 1 then it will set the enum value to TypeTwo instead of TypeOne like it should. Maybe I need a Default = 0 value in my enum for this to work? But there has to be a better way, because what if my values are not in sequence.
Your error won't be coming from the line you showed it on. I strongly suspect it's coming from this line:
FeedControl.FeedType = feedType;
My guess is that that property is doing some validation - and that it doesn't know about the relevant value.
EDIT: Note that if you do want to find out if a value is valid, use Enum.IsDefined. Enum.Parse will not throw an exception for an incorrect numeric value, so long as it's in the right range.
Have you really posted the exact code of the enum? Because if it doesn't explicitly specify the "= 1" and "= 2" it will autoincrement from 0, and that will be your problem.
If you could demonstrate all of this with a short but complete program it would really help. There's no need to go to the database, and no need to do anything with a user control.
I just tried the following and it worked perfectly. You might want to break your code out into a little test project to see what's going on.
// enum definition
public enum EFeedType {
TypeOne = 1,
TypeTwo = 2,
}
// usage
private void TestEnum() {
Int32 feedId = 2;
EFeedType stuff = (EFeedType)Enum.Parse(typeof(EFeedType), feedId.ToString());
Response.Write(stuff.ToString());
}
say I have the following declarations:
public enum Complexity { Low = 0, Normal = 1, Medium = 2, High = 3 }
public enum Priority { Normal = 1, Medium = 2, High = 3, Urgent = 4 }
and I want to code it so that I could get the enum value (not the index, like I earlier mentioned):
//should store the value of the Complexity enum member Normal, which is 1
int complexityValueToStore = EnumHelper.GetEnumMemberValue(Complexity.Normal);
//should store the value 4
int priorityValueToStore = EnumHelper.GetEnumMemberValue(Priority.Urgent);
How should this reusable function look like?
tia!
-ren
Revised answer (after question clarification)
No, there's nothing cleaner than a cast. It's more informative than a method call, cheaper, shorter etc. It's about as low impact as you could possibly hope for.
Note that if you wanted to write a generic method to do the conversion, you'd have to specify what to convert it to as well: the enum could be based on byte or long for example. By putting in the cast, you explicitly say what you want to convert it to, and it just does it.
Original answer
What do you mean by "index" exactly? Do you mean the numeric value? Just cast to int. If you mean "position within enum" you'd have to make sure the values are in numeric order (as that's what Enum.GetValues gives - not the declaration order), and then do:
public static int GetEnumMemberIndex<T>(T element)
where T : struct
{
T[] values = (T[]) Enum.GetValues(typeof(T));
return Array.IndexOf(values, element);
}
You can find the integer value of an enum by casting:
int complexityValueToStore = (int)Complexity.Normal;
The most generic way I know of is to read the value__ field using reflection.
This approach makes no assumptions about the enum's underlying type so it will work on enums that aren't based on Int32.
public static object GetValue(Enum e)
{
return e.GetType().GetField("value__").GetValue(e);
}
Debug.Assert(Equals(GetValue(DayOfWeek.Wednesday), 3)); //Int32
Debug.Assert(Equals(GetValue(AceFlags.InheritOnly), (byte) 8)); //Byte
Debug.Assert(Equals(GetValue(IOControlCode.ReceiveAll), 2550136833L)); //Int64
Note: I have only tested this with the Microsoft C# compiler. It's a shame there doesn't appear to be a built in way of doing this.
I realize this isn't what you asked, but it's something you might appreciate.
I discovered that you can find the integer value of an enum without a cast, if you know what the enum's minimum value is:
public enum Complexity { Low = 0, Normal = 1, Medium = 2, High = 3 }
int valueOfHigh = Complexity.High - Complexity.Low;
This wouldn't work with Priority, unless you added some minimal value of 0, or added 1 back:
public enum Priority { Normal = 1, Medium = 2, High = 3, Urgent = 4 }
int valueOfUrgent = Priority.Urgent - Priority.Normal + 1;
I find this technique much more aesthetically appealing than casting to int.
I'm not sure off the top of my head what happens if you have an enum based on byte or long -- I suspect that you'd get byte or long difference values.
If you want the value, you can just cast the enum to int. That would set complexityValueToStore == 1 and priorityValueToStore == 4.
If you want to get the index (ie: Priority.Urgent == 3), you could use Enum.GetValues, then just find the index of your current enum in that list. However, the ordering of the enum in the list returned may not be the same as in your code.
However, the second option kind of defeats the purpose of Enum in the first place - you're trying to have discrete values instead of lists and indices. I'd rethink your needs if that is what you want.
This is the most simple way to solve your problem:
public static void GetEnumMemberValue<T>(T enumItem) where T : struct
{
return (int) Enum.Parse(typeof(T), enumItem.ToString());
}
It works for me.
class Program
{
static void Main(string[] args)
{
String value = "Two";
Type enumType = typeof(Numbers);
Numbers number = (Numbers)Enum.Parse(enumType, value);
Console.WriteLine(Enum.Parse(enumType, value));
}
public enum Numbers : int
{
One,
Two,
Three,
Four,
FirstValue = 1
}
}
This is a simplified version of an enum I use in an application. The reason to why some of the enum names doesn't have a value is because I do Enum.Parse with their names as argument, while the ones with a value is parsed from an int.
If you would step through the code above and investigate the 'number' variable, you would see that it in fact is 'Two', but the output in console is 'FirstValue'. At this point I can't see why, do you?
Okay, the solution is simple - just give the valueless enums a value. But I'm still curious.
I suspect that both FirstValue and Two have an internal value of 1, so the system doesn't know which string to output.
public enum Numbers : int
{
One, // defaults to 0
Two, // defaults to 1
Three, // defaults to 2
Four, // defaults to 3
FirstValue = 1 // forced to 1
}
There is a unique integer value for every enum value, but there is not a unique enum value for every integer value.
When you parse "two", it gets stored internally as the integer 1. Then when you try and convert it back to a string, depending on the technique used to lookup that name, you could get either "Two" or "FirstValue". As you stated, the solution is to give every enum value a defined integer value.
Here is an interesting twist to your problem, try the following Enum...
public enum Numbers : int
{
One,
Two,
Four,
FirstValue = 1
}
The console.WriteLine(...) will now print "Two"!
Both Two and FirstValue represent the same number 1 but the actual value seen depends on how the number was converted to its string representation and vice-versa.
The Enum class uses reflection to get the names of the numbers and then stores them in arrays but it sorts the the whole thing before it does so. Then Enum.ToString() does a binary search on the sorted values to get the string representation. Due to the way this is done you may get a different result depending on the number of elements you have in the enumeration!
Now as for the value "seen" in VS I suspect the debugger visualizer for enums uses an algorithm of its own which corrects(?) this bug.