简体   繁体   中英

Dictionary of Enum Values as strings

I am trying to make an API, one function in that API takes Enum as parameter which then corresponds to a string which is used.

public enum PackageUnitOfMeasurement
{
        LBS,
        KGS,
};

The trivial method to code this will have to list every case in code. But as their are 30 cases so I am trying to avoid that and use Dictionary Data Structure , but I can't seem to connect the dots on how will I relate value to enum.

if(unit == PackageUnitOfMeasurement.LBS)
       uom.Code = "02";  //Please note this value has to be string
else if (unit == PackageUnitOfMeasurement.KGS)
       uom.Code = "03";

Here is one way you could store the mapping in a dictionary and retrieve values later:

var myDict = new Dictionary<PackageUnitOfMeasurement,string>();
myDict.Add(PackageUnitOfMeasurement.LBS, "02");
...

string code = myDict[PackageUnitOfMeasurement.LBS];

Another option is to use something like the DecriptionAttribute to decorate each enumeration item and use reflection to read these out, as described in Getting attributes of Enum's value :

public enum PackageUnitOfMeasurement
{
        [Description("02")]
        LBS,
        [Description("03")]
        KGS,
};


var type = typeof(PackageUnitOfMeasurement);
var memInfo = type.GetMember(PackageUnitOfMeasurement.LBS.ToString());
var attributes = memInfo[0].GetCustomAttributes(typeof(DescriptionAttribute),
    false);
var description = ((DescriptionAttribute)attributes[0]).Description;

The benefit of the second approach is that you keep the mapping close to the enum and if either changes, you don't need to hunt for any other place you need to update.

You can specify the number value of the enum elements

public enum PackageUnitOfMeasurement {
    None = 0,
    LBS = 2,
    KGS = 3,
    TONS = 0x2a
};

Then you can simply convert the units with

uom.Code = ((int)unit).ToString("X2");

NOTE:

The fundamental question is, whether it is a good idea to hard-code the units. Usually this sort of things should be put into a lookup table in a DB, making it easy to add new units at any time without having to change the program code.


UPDATE:

I added an example containing a HEX code. The format "X2" yields a two digit hex value. Enter all numbers greater than 9 in hex notation like 0xA == 10 , 0x10 == 16 in c#.

I would use attributes attached to the enum. Like this:

var type = typeof(PackageUnitOfMeasurement);
var memInfo = type.GetMember(PackageUnitOfMeasurement.LBS.ToString());
var attributes = memInfo[0].GetCustomAttributes(typeof(DescriptionAttribute),
    false);
var description = ((DescriptionAttribute)attributes[0]).Description;

This is taken from this question, Getting attributes of Enum's value . Which asks specifically about returning Enum attributes.

Oded's solution is fine, but an alternative that I've used in the past is to use attributes attached to the enum values that contain the corresponding string.

Here's what I did.

public class DisplayStringAttribute : Attribute
{
    private readonly string value;
    public string Value
    {
        get { return value; }
    }

    public DisplayStringAttribute(string val)
    {
        value = val;
    }
}

Then I could define my enum like this:

public enum MyState 
{ 
    [DisplayString("Ready")]
    Ready, 
    [DisplayString("Not Ready")]
    NotReady, 
    [DisplayString("Error")]
    Error 
};

And, for my purposes, I created a converter so I could bind to the enum:

public class EnumDisplayNameConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        Type t = value.GetType();
        if (t.IsEnum)
        {
            FieldInfo fi = t.GetField(value.ToString());
            DisplayStringAttribute[] attrbs = (DisplayStringAttribute[])fi.GetCustomAttributes(typeof(DisplayStringAttribute),
                false);
            return ((attrbs.Length > 0) && (!String.IsNullOrEmpty(attrbs[0].Value))) ? attrbs[0].Value : value.ToString();
        }
        else
        {
            throw new NotImplementedException("Converter is for enum types only");
        }
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

Oded's solution probably performs faster, but this solution has a lot of flexibility. You could add a whole bunch of attributes if you really wanted to. However, if you did that, you'd probably be better off creating a class rather than using an enum!

The default value of PackageUnitOfMeasurement.LBS is 0 likewise PackageUnitOfMeasurement.KBS is 1 .

So a collection of PackageUnitOfMeasurement is really a collection that contain integer values ( ie int ).

Your question is not entirely clear....

A Dictionary collection has a Key and a Value it sounds like you want use PackageUnitOfMeasurement has a Key which is trivial as casting the value to an integer.

PackageUnitOfMeasurement example = PackageUnitOfMeasurement.LBS
int result = (int)example;
var myDict = new Dictionary<PackageUnitOfMeasurement,string>(); 
myDict.Add(result,"some value here"

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM