48

I have a combo box where I am displaying some entries like:

Equals
Not Equals 
Less Than
Greater Than

Notice that these strings contain spaces. I have a enum defined which matches to these entries like:

enum Operation{Equals, Not_Equals, Less_Than, Greater_Than};

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#?

Naveen
  • 74,600
  • 47
  • 176
  • 233
  • strongly related: [how-to-set-space-on-enum](http://stackoverflow.com/questions/1101872/how-to-set-space-on-enum) – nawfal Jun 09 '13 at 12:11
  • 1
    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](http://www.codeducky.org/ins-outs-c-enums/). – ChaseMedallion Jul 20 '14 at 20:14

8 Answers8

89

I suggest building a Dictionary<string, Operation> 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<string, Operation> {
    { "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(' ', '_'));
Mehrdad Afshari
  • 414,610
  • 91
  • 852
  • 789
  • 2
    Out of interest, why do you recommend against using Enum.Parse? more conversions? – Pondidum Jul 27 '09 at 08:50
  • 23
    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). – Mehrdad Afshari Jul 27 '09 at 09:06
22
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(" ", "_"));
Nick Strupat
  • 4,928
  • 4
  • 44
  • 56
AdaTheDev
  • 142,592
  • 28
  • 206
  • 200
19

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 Dictionary<string, Operation> operationMap;

    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:

Richard Szalay
  • 83,269
  • 19
  • 178
  • 237
9

You can use the Parse method:

 Operarion operation = (Operation)Enum.Parse(typeof(Operation), "Not_Equals");

Some examples here

Samuel Carrijo
  • 17,449
  • 12
  • 49
  • 59
1

Why use another way : convert Enumeration to String?

Just generate the items of your combo box from your Enumeration.

faceclean
  • 3,781
  • 8
  • 39
  • 58
1

in C#, you can add extension methods to enum types. See http://msdn.microsoft.com/en-us/library/bb383974.aspx

You could use this approach to add toString(Operation op), fromString(String str) and toLocalizedString(Operation op) methods to your enum types. The method that you use to lookup the particular string depends on your application and should be consistent with what you do in similar cases. Using a dictionary as others have suggested seems like a good first approach as long as you don't need full localization in your app.

VoidPointer
  • 17,651
  • 15
  • 54
  • 58
1

I would use a singleton of this enum mapper class that performs much faster than Enum.Parse (which uses reflection and is really slow). You can then use EnumFromString(typeof(YourEnum), "stringValue") to get your enum.

arviman
  • 5,087
  • 41
  • 48
1

As of C# 8 you can do that using switches. In your example I believe the code would be like this.

enum Operation{Equals, Not_Equals, Less_Than, Greater_Than};

public static string OperationString(Operation opString) =>
    opString switch
    {
        Operation.Equals => "Equals",
        Operation.Not_Equals => "Not Equals",
        Operation.Less_Than=> "Less Than",
        Operation.Greater_Than=> "Greater Than",
        _   => throw new ArgumentException(message: "invalid enum value", paramName: nameof(opString )),
    };

See here for the documentation.

A_Arnold
  • 3,195
  • 25
  • 39