3

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";
Ben Hoffman
  • 8,149
  • 8
  • 44
  • 71
PUG
  • 4,301
  • 13
  • 73
  • 115
  • 1
    `Please note this value has to be string` - but will all the string values be string representations of integers, and distinct integers at that? If so you should set the integer underlying each enum value, and then write a function to correctly convert the integers to the string representation you want e.g. 2=> "02" etc. – Rawling Mar 08 '12 at 14:00
  • +1 Did came across a sample code for setting enum values in code and that is surely more simple, but in my case value can also be "2a" – PUG Mar 08 '12 at 14:09
  • Fair enough. Bang goes the simple solution! – Rawling Mar 08 '12 at 14:11

5 Answers5

9

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.

Community
  • 1
  • 1
Oded
  • 489,969
  • 99
  • 883
  • 1,009
4

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

Olivier Jacot-Descombes
  • 104,806
  • 13
  • 138
  • 188
2

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.

Community
  • 1
  • 1
Ben Hoffman
  • 8,149
  • 8
  • 44
  • 71
1

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!

Matt Burland
  • 44,552
  • 18
  • 99
  • 171
0

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 ( i.e. 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"
Security Hound
  • 2,577
  • 3
  • 25
  • 42