Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Enum item mapped to another value

Tags:

c#

I have enum:

enum MyEnum{
    aaaVal1,
    aaaVal2,
    aaaVal3,
}  

I need to have abbreviated version of 'MyEnum' which maps every item from 'MyEnum' to different values. My current approach is method which simply translates every item:

string translate(MyEnum myEnum)
{
    string result = "";
    switch ((int)myEnum)
    {
        0:   result = "abc";
        1:   result = "dft";
        default: result = "fsdfds"
    }
    return result;
}

the problem with this approach is that every time programmer changes MyEnum he should also change translate method.

This is not a good way of programming.

So..

Is there any more elegant solution for this problem?

Thank you :-)

like image 495
Jacek Wojcik Avatar asked Aug 20 '13 07:08

Jacek Wojcik


People also ask

Can enum be used for mapping?

A specialized Map implementation for use with enum type keys. All of the keys in an enum map must come from a single enum type that is specified, explicitly or implicitly, when the map is created. Enum maps are represented internally as arrays. This representation is extremely compact and efficient.

Can enum have multiple values?

The Enum constructor can accept multiple values.

How do you Map a string to an enum?

You can create Enum from String by using Enum. valueOf() method. valueOf() is a static method that is added on every Enum class during compile-time and it's implicitly available to all Enum along with values(), name(), and cardinal() methods.


2 Answers

Four options:

  • Decorate your enum values with attributes, e.g.

    enum MyEnum
    {
        [Description("abc")]
        AaaVal1,
        [Description("dft")]
        AaaVal2,
        AaaVal3,
    } 
    

    Then you can create a mapping (like the dictionary solution below) via reflection.

  • Keep the switch statement but switch on the enum value instead of a number for better readability:

    switch (myEnum)
    {
        case MyEnum.AaaVal1: return "abc";
        case MyEnum.AaaVal2: return "dft";
        default:             return "fsdfds";
    }
    
  • Create a Dictionary<MyEnum, string>:

    private static Dictionary<MyEnum, string> EnumDescriptions = 
        new Dictionary<MyEnum, string>
    {
        { MyEnum.AaaVal1, "abc" },
        { MyEnum.AaaVal2, "dft" },        
    };
    

    You'd need to handle the defaulting in the method, of course.

  • Use a resource file, with an entry for each string representation. This would be better if you're really trying to translate in a way that might need different translations for different cultures.

like image 71
Jon Skeet Avatar answered Sep 19 '22 12:09

Jon Skeet


Considering that the use of descriptors on enums is quite common, here it's a good-enough class to do it:

[AttributeUsage(AttributeTargets.Field, AllowMultiple = false)]
class EnumDescriptor : Attribute
{
    public readonly string Description;

    public EnumDescriptor(string description)
    {
        this.Description = description;
    }

    public static string GetFromValue<T>(T value) where T : struct
    {
        var type = typeof(T);
        var memInfo = type.GetField(value.ToString());
        var attributes = memInfo.GetCustomAttributes(typeof(EnumDescriptor), false);

        if (attributes.Length == 0)
        {
            return null;
        }

        return ((EnumDescriptor)attributes[0]).Description;
    }
}

enum MyEnum
{
    [EnumDescriptor("Hello")]
    aaaVal1,
    aaaVal2,
    aaaVal3,
}  

string translate(MyEnum myEnum)
{
    // The ?? operator returns the left value unless the lv is null,
    // if it's null it returns the right value.
    string result = EnumDescriptor.GetFromValue(myEnum) ?? "fsdfds";
    return result;
}
like image 28
xanatos Avatar answered Sep 19 '22 12:09

xanatos