0

Is it possible to iterate through properties of a custom enum?

My custom enum looks like this:

public class Sex
{
    public static readonly Sex Female = new Sex("xx", "Female");

    public static readonly Sex Male = new Sex("xy", "Male");

    internal string Value { get; private set; }

    internal string Description { get; private set; }

    public override string ToString()
    {
        return Value.ToString();
    }

    public string GetDescription()
    {
        return this.Description;
    }

    protected Sex(string value, string description)
    {
        this.Value = value;
        this.Description = description;
    }

I use it to enable an enum to "enumerate" with strings i.e. "xx", "xy"...

My question is if it is possible to iterate though all sexes with the goal to fill a DropDownList ListItems with value and description.

var ddlSex = new DropDownList()

foreach(var sex in typeof(Sex).<some_magic>)
{
    ddlSex.Items.Add(new ListItem(sex.ToString(), sex.GetDescription()));
}

My idea is to solve the problem with the System.Reflection library but I'm sure how.

Christoph Brückmann
  • 1,373
  • 1
  • 23
  • 41

2 Answers2

3
var list = typeof(Sex).GetFields(BindingFlags.Static | BindingFlags.Public)
            .Select(f => (Sex)f.GetValue(null))
            .ToList();

foreach(var sex in list)
{
    Console.WriteLine(sex.ToString() + ":" + sex.GetDescription());
}
L.B
  • 114,136
  • 19
  • 178
  • 224
  • Definitely the right solution, but as I mentioned in my answer, it's worth organising your code so that the evaluation of list only happens once in your application runtime. – Rob Lyndon Mar 11 '14 at 22:07
  • @RobLyndon I'll leave that part to the OP since it is not the point of the question. – L.B Mar 11 '14 at 22:13
  • @RobLyndon It would be nice to use it the way you described but "var sex" contains two elements which are "null" each containing the static members "Female" and "Male". – Christoph Brückmann Mar 11 '14 at 22:20
  • 2
    @RobLyndon + Christoph Brückmann, because it depends on the **order** of the fields' initialization. It should be done in a *static* constructor of the class, like `static Sex() { All = ... }` – L.B Mar 11 '14 at 22:26
  • @L.B You're absolutely right. Thanks a lot (to both of you)! :) – Christoph Brückmann Mar 11 '14 at 22:34
1

When you use reflection, you should try to do it in one hit: usually in a static constructor.

Here, you could do this:

public class Sex
{
    public static readonly List<Sex> All = typeof(Sex).GetFields(BindingFlags.Public | BindingFlags.Static)
        .Where(f => f.FieldType == typeof(Sex))
        .Select(f => (Sex)f.GetValue(null))
        .ToList();

    public static readonly Sex Female = new Sex("xx", "Female");

    public static readonly Sex Male = new Sex("xy", "Male");

    ...
}

Then you can just use Sex.All, and the reflection will only happen once in your runtime. Your invocation will look like this:

foreach(var sex in Sex.All)
{
    this.ddlSex.Items.Add(new ListItem(sex.ToString(), sex.GetDescription()));
}
Rob Lyndon
  • 12,089
  • 5
  • 49
  • 74