views:

1604

answers:

6

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

+13  A: 

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
Out of interest, why do you recommend against using Enum.Parse? more conversions?
Pondidum
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
+4  A: 

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
There seems to be something missing... enumType is never declared, GetDisplayName is calling with one parameter but has 2 parameters declared.
Jeff Martin
Correction: enumType is never declared in the static constructor
Jeff Martin
also it doesn't appear that you can use the DisplayName attribute on enum declarations
Jeff Martin
+1  A: 
Operation enumVal = (Operation)Enum.Parse(typeof(Operation), "Equals")

For "Not Equals", you obv need to replace spaces with underscores in the above statement

AdaTheDev
That will not match "Not Equals" to Operation.Not_Equals
Richard Szalay
That's whay I said you'd need to do a replace on the value to replace spaces with underscores so it will match...
AdaTheDev
A: 

You can use the Parse method:

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

Some examples here

Samuel Carrijo
A: 

Why use another way : convert Enumeration to String?

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

ablmf
A: 

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