views:

283

answers:

4

So currently have an enumeration used on the status of an application. However, something feels off when using it against the ui. To many conversions between integer and string when populating drop downs. I could use an extension method or the type converter and continue to use the enum which will be helpful if an enum has multiple words in it.

Thought I'd ask to see about filling in a possible hole before I dig it to deep.

Thanks.

A: 

use an integer instead, write comments for its status in code, no further conversion needed

HPT
You suspect the OP would like to display integers in his drop down menus?
Kirk Woll
I like it. "I need the unit price of this product, so I can make it a status four." "It's the same as the old status-seven product it's replacing. Just switch it back to six to see the old unit price." :-)
Jeffrey L Whitledge
+5  A: 

If you are working with a variable that has a finite and well-known number of possible states, then an enum is indeed the correct construct for you to use. There are many possible ways to make working with the UI more convenient, and you have cited two excellent ones, which are type converters and extension methods.

Mark
+13  A: 

My team had this issue in our recent project. We kept the enums, because they are the thing to use for a finite list of known constant values, but we did a few things to make them more developer-friendly:

  1. We decorated the enum values with [Description()] attributes containing the "friendly name" of each enum constant.
  2. We created a GetDescription() extension method that would reflectively examine the enum constant's Description attribute and return the friendly name. If it doesn't have one, the method attempts to insert spaces into the ToString() of the enum constant name. As CamelCased enum constants were a style requirement enforced by ReSharper, this worked for about 90% of our constants, and Description attributes handled the rest (mostly uppercase acronyms in the name).
  3. We created a ParseEnum() generic extension method for strings that basically wraps Enum.Parse() (which is oogly; requires specifying the Enum type in the method and then casting to it). I think it may be smart enough to try looking for description attributes first, or else we simply use the still-readable ToString() representation as the data value of the drop-down item.

So, given the following:

public enum MyItems
{
   [Description("Item One")]
   ItemOne,
   [Description("Item Two")]
   ItemTwo,
   [Description("Item Three")]
   ItemThree
}

we could populate a DropDownList with user-friendly choices in two lines:

foreach(MyValues value in Enum.GetValues<MyValues>())
   myDDL.Items.Add(New ListItem(value.GetDescription(), value.ToString())

... and then we could parse the selection back out with very readable code:

var theValue = myDDL.SelectedItem.Value.ParseEnum<MyValues>()

EDIT: I have been asked for the GetDescription() method. I'm a little iffy about sharing the whole thing, but here's the basic algorithm for getting a Description attribute that decorates an enum constant. Parsing a CamelCased name is pretty straightforward RegEx splits on capital letters, and our implementation's a little naive anyway. This snippet requires System.ComponentModel.DescriptionAttribute (which is also the decorator for the enum constants), and enumType is the "this" parameter of the extension method, of type Enum:

var attr = enumType.GetType().GetField(enumType.ToString())
                 .GetCustomAttributes(typeof(DescriptionAttribute), false);
   if (attr.Length > 0)
      return ((DescriptionAttribute)attr[0]).Description;
KeithS
All very good suggestions. Any time I set up a new project my Parse<T> method is always shoved in :)
Mark Simpson
Yikes! Beauty :-) Could I ask for your GetDescription extension. For the same purpose I wrote special dictionary class with names of enums, but your approach seems more clean.
macias
By hard-coding the user-visible name in code, you're committing to re-building and re-distributing the entire app, if the client decides they want to see "Item 1" instead of "Item One". You're also preventing the system from being localized through use of resource files/satellite assemblies.
mikemanne
@mikemanne - Everything you said is true. In our case, these were not major concerns; the change is trivial to make and include in a release schedule, and this was an Intranet, English-only app. However, these concerns are significant for someone developing a multilingual app, and I wouldn't recommend this exact solution then. The Description could be given a layer of abstraction to a value in multilingual label tables in the DB, or to some config file, and GetDescription extended to go look for it given a language. All of these will add complexity and can make other changes more difficult.
KeithS
A: 

An Enum like construct is definitely the right choice. If for some reason you don't want to use the familiar built in way, you can make you're own with a bir more functionaliy. here's the basic idea:

class Country {
    private static Country US;
    private static Country JP

    static Country() { //initialize static variables }
    private Country( string name ) { //initialize variables of Country instance }

    }

There's a design pattern for this, but I forget the name.

CrazyJugglerDrummer
I remember doing this at some point somewhere, however is this really preferable to a enum or is there that big a difference? The enum does give me an integer value to correspond to IDs iny my database which means one less conversion. Off to do some research, thanks.
Aur