Convert a string to an enum in C#
What’s the best way to convert a string to an enumeration value in C#? I have an HTML select tag containing the values of an enumeration. When the page is posted, I want to pick up the value (which will be in the form of a string) and convert it to the corresponding enumeration value. In an ideal world, I could do something like this:
StatusEnum MyStatus = StatusEnum.Parse("Active");
29 Answers 29
In .NET Core and .NET Framework ≥4.0 there is a generic parse method:
Enum.TryParse("Active", out StatusEnum myStatus);
This also includes C#7’s new inline out variables, so this does the try-parse, conversion to the explicit enum type and initialises+populates the myStatus variable.
If you have access to C#7 and the latest .NET this is the best way.
Original Answer
In .NET it’s rather ugly (until 4 or above):
StatusEnum MyStatus = (StatusEnum) Enum.Parse(typeof(StatusEnum), "Active", true);
I tend to simplify this with:
public static T ParseEnum(string value)
StatusEnum MyStatus = EnumUtil.ParseEnum("Active");
One option suggested in the comments is to add an extension, which is simple enough:
public static T ToEnum(this string value) < return (T) Enum.Parse(typeof(T), value, true); >StatusEnum MyStatus = "Active".ToEnum();
Finally, you may want to have a default enum to use if the string cannot be parsed:
public static T ToEnum(this string value, T defaultValue) < if (string.IsNullOrEmpty(value)) < return defaultValue; >T result; return Enum.TryParse(value, true, out result) ? result : defaultValue; >
Which makes this the call:
StatusEnum MyStatus = "Active".ToEnum(StatusEnum.None);
However, I would be careful adding an extension method like this to string as (without namespace control) it will appear on all instances of string whether they hold an enum or not (so 1234.ToString().ToEnum(StatusEnum.None) would be valid but nonsensical) . It’s often be best to avoid cluttering Microsoft’s core classes with extra methods that only apply in very specific contexts unless your entire development team has a very good understanding of what those extensions do.
If performace is important (which always is) chk answer given by Mckenzieg1 below : stackoverflow.com/questions/16100/…
@avinashr is right about @McKenzieG1’s answer, but it isn’t ALWAYS important. For instance it would be a pointless micro optimisation to worry about enum parsing if you were making a DB call for each parse.
@H.M. I don’t think an extension is appropriate here — it’s a bit of a special case and an extension would apply to every string. If you really wanted to do it though it would be a trivial change.
StatusEnum myStatus; Enum.TryParse("Active", out myStatus);
It can be simplified even further with C# 7.0’s parameter type inlining:
Enum.TryParse("Active", out StatusEnum myStatus);
Add the middle boolean parameter for case-sensitivity and this is the safest and most elegant solution by far.
Come on, how many of you implemented that selected answer from 2008 to only scroll down and find this is the better (modern) answer.
I don’t get it. Parse throws explanatory exceptions for what went wrong with the conversion (value was null , empty or no corresponding enum constant), which is way better than TryParse ‘s boolean return value (which suppresses the concrete error)
Enum.TryParse
@MassDotNet In that case add: && Enum.IsDefined(typeof(System.DayOfWeek), parsedEnum) to ensure that the parsed Enum actually exists.
Note that the performance of Enum.Parse() is not ideal, because it is implemented via reflection. (The same is true of Enum.ToString() , which goes the other way.)
If you need to convert strings to Enums in performance-sensitive code, your best bet is to create a Dictionary at startup and use that to do your conversions.
While 3ms first-run is definitely awful, would the second run be any better? If it’s 3ms everytime then we’d avoid it like plague
Enum.Parse takes nanoseconds, not milliseconds, at least using modern .NET versions. I tested this code using BenchmarkDotNet in .NET 6: MyEnum myEnum = Enum.Parse
And .NET Framework is nearly as fast as .NET 6, running the following code in 175 ns on all .NET Framework versions 4.6.1-4.8.1: Enum.TryParse(Input, out MyEnum result); . This is not «awful».
SomeEnum enum = (SomeEnum)Enum.Parse(typeof(SomeEnum), "EnumValue");
public static T ToEnum(this string value, bool ignoreCase = true)
And you can call them by the below code (here, FilterType is an enum type):
FilterType filterType = type.ToEnum();
I have updated this to take the value as object and cast it to string inside this method. This way I can take an int value .ToEnum instead of strings only.
@SollyM I’d say that’s a horrible idea cause then this extension method will apply to all object types. Two extension methods, one for string and one for int, would be cleaner and much safer in my opinion.
@Svish, that’s true. The only reason I did this is because our code is used internally only and I wanted to avoid writing 2 extensions. And since the only time we convert to Enum is with string or int, I didn’t see it being a problem otherwise.
@SollyM Internal or not, I’m still the one maintaining and using my code 😛 I would be annoyed if I got up a ToEnum in every intellisense menu, and like you say, since the only time you convert to an enum is from string or int, you can be pretty sure you’ll only need those two methods. And two methods aren’t that much more than one, especially when they are this small and of the utility type 😛
Enum.(Try)Parse() accepts multiple, comma-separated arguments, and combines them with binary ‘or’ | . You cannot disable this and in my opinion you almost never want it.
var x = Enum.Parse("One,Two"); // x is now Three
Even if Three was not defined, x would still get int value 3 . That’s even worse: Enum.Parse() can give you a value that is not even defined for the enum!
I would not want to experience the consequences of users, willingly or unwillingly, triggering this behavior.
Additionally, as mentioned by others, performance is less than ideal for large enums, namely linear in the number of possible values.
public static bool TryParse(string value, out T result) where T : struct < var cacheKey = "Enum_" + typeof(T).FullName; // [Use MemoryCache to retrieve or create&store a dictionary for this enum, permanently or temporarily. // [Implementation off-topic.] var enumDictionary = CacheHelper.GetCacheItem(cacheKey, CreateEnumDictionary, EnumCacheExpiration); return enumDictionary.TryGetValue(value.Trim(), out result); > private static Dictionary CreateEnumDictionary() < return Enum.GetValues(typeof(T)) .Cast() .ToDictionary(value => value.ToString(), value => value, StringComparer.OrdinalIgnoreCase); >
String to enum conversion in C#
Since space is not allowed, I have used _ character. Now, is there any way to convert given string automatically to an enum element without writing a loop or a set of if conditions my self in C#?
In addition to the dictionary approach below, you can use attributes to associate metadata (like display strings) with an enum. Check out The ins and outs of C# enums.
8 Answers 8
I suggest building a Dictionary to map friendly names to enum constants and use normal naming conventions in the elements themselves.
enum Operation< Equals, NotEquals, LessThan, GreaterThan >; var dict = new Dictionary < < "Equals", Operation.Equals >, < "Not Equals", Operation.NotEquals >, < "Less Than", Operation.LessThan >, < "Greater Than", Operation.GreaterThan >>; var op = dict[str];
Alternatively, if you want to stick to your current method, you can do (which I recommend against doing):
var op = (Operation)Enum.Parse(typeof(Operation), str.Replace(' ', '_'));
I’m not against Enum.Parse method. I’m against tightly coupling user interface strings to code elements (and changing code according to display names).
Operation enumVal = (Operation)Enum.Parse(typeof(Operation), "Equals")
For «Not Equals», you obv need to replace spaces with underscores in the above statement
EDIT: The following version replaces the spaces with underscores before attempting the parsing:
string someInputText; var operation = (Operation)Enum.Parse(typeof(Operation), someInputText.Replace(" ", "_"));
That’s whay I said you’d need to do a replace on the value to replace spaces with underscores so it will match.
Either create a dedicated mapper using a dictionary (per Mehrdad’s answer) or implement a TypeConverter.
Your custom TypeConverter could either replace » » -> «_» (and vice versa) or it could reflect the enumeration and use an attribute for determining the display text of the item.
enum Operation < [DisplayName("Equals")] Equals, [DisplayName("Not Equals")] Not_Equals, [DisplayName("Less Than")] Less_Than, [DisplayName("Greater Than")] Greater_Than >; public class OperationTypeConverter : TypeConverter < private static DictionaryoperationMap; static OperationTypeConverter() < BindingFlags bindingFlags = BindingFlags.Static | BindingFlags.GetField | BindingFlags.Public; operationMap = enumType.GetFields(bindingFlags).ToDictionary( c =>GetDisplayName(c) ); > private static string GetDisplayName(FieldInfo field, Type enumType) < DisplayNameAttribute attr = (DisplayNameAttribute)Attribute.GetCustomAttribute(typeof(DisplayNameAttribute)); return (attr != null) ? attr.DisplayName : field.Name; >public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) < string stringValue = value as string; if (stringValue != null) < Operation operation; if (operationMap.TryGetValue(stringValue, out operation)) < return operation; >else < throw new ArgumentException("Cannot convert '" + stringValue + "' to Operation"); >> > >
This implementation could be improved in several ways:
Enum from string, int, etc
Using extension method we can create methods to convert an enum to other datatype like string, int by creating extension methods ToInt() , ToString() , etc for the enum. I wonder how to implement the other way around, e.g. FromInt(int) , FromString(string) , etc. As far as I know I can’t create MyEnum.FromInt() (static) extension method. So what are the possible approaches for this?
wouldn’t that kind of pollute int and string since they are used a lot and mostly not related to my enum?
Such a method (like my ToEnum<> below) would be general purpose enough (almost like ToString(), almost).
7 Answers 7
I would avoid polluting int or string with extension methods for enums, instead a good old fashioned static helper class might be in order.
public static class EnumHelper < public static T FromInt(int value) < return (T)value; >public static T FromString(string value) < return (T) Enum.Parse(typeof(T),value); >>
I’m not even calling it and compilation fails — I got this to work instead: public static T ToEnum(this int value)
Big chances of getting exceptions, I would use a combination of this solutions with Reddeckwins’s solution below (using IsDefined and TryParse) to avoid unnecessary problems, of course depending on the situation.
Do you really need those extension methods?
MyEnum fromInt = (MyEnum)someIntValue; MyEnum fromString = (MyEnum)Enum.Parse(typeof(MyEnum), someStringValue, true); int intFromEnum = (int)MyEnum.SomeValue; string stringFromEnum = MyEnum.SomeValue.ToString();
The other way around would be possibly. the other way around 😉 Extend int and string with generic extension methods which will take as type parameter the type of an enum:
public static TEnum ToEnum(this int val)
public static TEnum ToEnum(this string val)
var redFromInt = 141.ToEnum(); var redFromString = "Red".ToEnum();
There is unfortunately no generic constraint for Enums, so we have to check TEnum type during runtime; to simplify we’ll leave that verification to Enum.ToObject and Enum.Parse methods.
why do you want FromInt an extenstion method versus just casting it?
MyEnum fromInt; if(Enum.IsDefined(typeof(MyEnum), intvalue)) < fromInt = (MyEnum) intvalue; >else < //not valid >
alternatively, for strings, you can use Enum.TryParse
MyEnum fromString; if (Enum.TryParse(stringvalue, out fromString)) < //succeeded >else < //not valid >
I don’t quite get what you are saying. Are you asking what happens in the string or int do not represent any of the enum values?
Another approach (for the string part of your question):
/// /// Static class for generic parsing of string to enum /// /// Type of the enum to be parsed to public static class Enum < /// /// Parses the specified value from string to the given Enum type. /// /// The value. /// public static T Parse(string value) < //Null check if(value == null) throw new ArgumentNullException("value"); //Empty string check value = value.Trim(); if(value.Length == 0) throw new ArgumentException("Must specify valid information for parsing in the string", "value"); //Not enum check Type t = typeof(T); if(!t.IsEnum) throw new ArgumentException("Type provided must be an Enum", "T"); return (T)Enum.Parse(typeof(T), value); >>
public static class EnumExtensions < public static Enum FromInt32(this Enum obj, Int32 value) < return (Enum)((Object)(value)); >public static Enum FromString(this Enum obj, String value) < return (Enum)Enum.Parse(obj.GetType(), value); >>
public static class Int32Extensions < public static Enum ToEnum(this Int32 obj) < return (Enum)((Object)(obj)); >> public static class StringExtensions < public static Enum ToEnum(this Enum obj, String value) < return (Enum)Enum.Parse(obj.GetType(), value); >>
You can either make extension methods on int and string.
Or make static method on some other static class. Maybe something like EnumHelper.FromInt(int).
But I would pose one question : Why do you want to convert to string or int? Its not how you normaly work with enumerables, except maybe serialisation. But that should be handled by some kind of infrastructure, not your own code.