Aug 14 2008

Foreaching in an enum’s values

Published by Renaud Bédard at 12:08 under C#

This post is BS. Read the notes at the bottom or the comments.

Here’s a very short and self-explanatory snippet that you might find useful.

Suppose you have an enum, like one describing the different states that an actor can take :

public enum ActorState
{
    Idle,
    Walking,
    Sliding,
    Jumping,
    Bouncing
}

This list is subject to change, because you’re still writing your actor’s code and expanding its actions.

And somewhere in your code you need to loop in all those states, like for example to do a ListBox values list to choose from in your editor. You’d have to do that :

for (ActorState i = ActorState.Idle; i <= ActorState.Bouncing; i++)
{
    // ...
}

And this is a bad idea for two reasons :

  • Whenever you add more actor states, you’ll have to change all your loops for them to see it.
  • If you use bit flags or manually set values to your enum fields, you might miss enum fields when incrementing, or you’ll reach values that don’t correspond to any enum field.

A simple solution to these problems is to use this method :

public static IEnumerable<T> Enumerate<T>() where T : struct
{
    foreach (object value in Enum.GetValues(typeof(T)))
        yield return (T)value;
}

This will return an enumerable, typesafe/strongly-typed collection of enumeration vaules that will catch everyone of them. It’s used like so :

foreach (ActorState state in Util.Enumerate<ActorState>())
{
    // ...
}

If you’re in C# 3.0, you can replace the “ActorState” loop variable declaration to a “var” and cut down on unnecessary code.
One problem with my method is that you can pass any struct, not just enums, and this will probably raise an exception. But hey, we’re all adults here,… garbage-in, garbage-out.

Oops…

As Brac suggested in the comments below, simply foreach’ing on what Enum.GetValues returns works just as well :

foreach (ActorState state in Enum.GetValues(typeof(ActorState)))
{
    // ...
}

I assumed (and I was pretty sure…) that this didn’t work since Enum.GetValues() returns an Array, which is not IEnumerable<T> so I thought it wouldn’t even compile. But it seems that implicit casting is done and it does work. Also it turns out that my combination of foreach and yield returns is too slow in time-critical sections.

6 responses so far

6 Responses to “Foreaching in an enum’s values”

  1. Weston 16 Aug 2008 at 13:31

    That is a nice snippet, but what about using

    [Enum].GetNames(GetType(ActorState))

    , I don’t know if this exists in C# but I think it should, it’s the way I get my Enums in my Tools in Combination with Parse to get the actual enumeration value:

    [Enum].Parse(GetType(ActorState), Value)

  2. Renaud Bédardon 16 Aug 2008 at 13:35

    Hmm, in that case you might like Enum.GetValues(), which is what my function uses internally. :P
    The point is that my wrapper function returns a strongly-typed enumerable, whereas Enum.GetValues() returns a dumb Array.

  3. Weston 16 Aug 2008 at 14:11

    Ah, lol, now I suddenly understand what you are doing, hm, I think it isn’t well if I sit the whole day infront of a computer coding, it makes one dumb :P .

    Nice code as always Zak, and thanks for sharing it.

  4. Bracon 18 Aug 2008 at 06:01

    Hm, i’m probably missing the point Zak.
    It’s nice to have the values strongly typed,
    but your solution is considerably slower than just using:

    foreach (ActorState state in Enum.GetValues(typeof(ActorState )))
    {
    // …
    }

    You loop twice, that’s really something to think about.

  5. Renaud Bédardon 18 Aug 2008 at 09:08

    I don’t loop twice, yield returns are executed on-demand, so it the same performance-wise as doing

    foreach (object state in Enum.GetValues(typeof(ActorState)))
    {
        ActorState state = (ActorState)state;
        // ...
    }

    That said… I didn’t know that the foreach you propose worked! And I feel really dumb for not trying it.
    I thought this would fail because the returned Array is not IEnumerable<ActorState>. But it does work, and it renders my method completely useless…

    I’ll edit my post. :/

  6. Anthony Reddanon 25 Sep 2008 at 23:56

    In case anyone is interested, the C++/CLI equivalent of typeof(ActorState) is ActorState::typeid.

Trackback URI | Comments RSS

Leave a Reply