10

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.

Aur
  • 191
  • 9
  • 1
    Had a similar, unrelated question with some good responses: http://stackoverflow.com/questions/1970594/enums-or-tables – Dustin Laine Aug 31 '10 at 21:44
  • is it correct to assume the ui you're using is with wpf? – Ashley Grenon Aug 31 '10 at 21:44
  • Are you opposed to just writing a static class that could do the same thing so that you could avoid the boxing issues? – joshlrogers Aug 31 '10 at 21:46
  • 1
    http://msmvps.com/blogs/deborahk/archive/2009/07/10/enum-binding-to-the-description-attribute.aspx – SwDevMan81 Aug 31 '10 at 22:28
  • I agree with KiethS, assuming his scenario reflects yours. The problem isn't the Enum structure, it's that you are replicating the effort to represent the value as friendly text. Do that once in a method, then call that method when you need it. –  Aug 31 '10 at 22:44
  • Trying to get back into using wpf. Not opposed to a static class, do you remember the design pattern by chance? I want to poke at the positive and negatives before doing a change like that. I believe I'm getting the feeling that using extension method and type converter is the way to go as said and explained below. However the static class is interesting. – Aur Sep 01 '10 at 02:00
  • "Just writing" a static class means you have to write all the time, so it is not "just". If anything it is better to write non-static class (for all enums) and then create static instance of it. – greenoldman Sep 01 '10 at 09:44

3 Answers3

14

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
  • 70,210
  • 21
  • 112
  • 164
  • All very good suggestions. Any time I set up a new project my Parse method is always shoved in :) – Mark Simpson Aug 31 '10 at 22:14
  • 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. – greenoldman Sep 01 '10 at 06:17
  • 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 Sep 01 '10 at 16:12
  • @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 Sep 01 '10 at 16:38
5

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
  • 11,257
  • 11
  • 61
  • 97
0

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.

Gordon Gustafson
  • 40,133
  • 25
  • 115
  • 157
  • 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 Sep 01 '10 at 01:56