views:

25075

answers:

11

How can you enumerate a enum in C#?

e.g. the following does not compile:

public enum Suit
{
 Spades,
 Hearts,
 Clubs,
 Diamonds
}

public void EnumerateAllSuitsDemoMethod()
{
 foreach (Suit suit in Suit)
 {
  DoSomething(suit);
 }
}

It gives the compile time error: 'Suit' is a 'type' but is used like a 'variable'

It fails on the Suit keyword, the 2nd one.

Edit: Got rid of Console.WriteLine(), it was confusing people

A: 

Enum.GetNames(Suits), I think...

Tom Carr
Enum.GetValues(Suits)
Ian Boyd
+176  A: 
foreach (Suit suit in Enum.GetValues(typeof(Suit)))
{
}
jop
I didn't know that. Nice to know!
unforgiven3
I've heard vague rumours that this is terifically slow. Anyone know?
Orion Edwards
Enumerating an enum with 52 values 100000 times: 3884msEnumerating an int[] with 52 values 100000 times: 99msyes, far slower than an array - but still fast unless you have 51 million enum values ;)
TheSoftwareJedi
Although, you're missing a close bracket on the foreach line :-)
Hainesy
@Hainesy - haha! stackoverflow needs more than a syntax hilighter. it needs a syntax checker. fixed.
jop
+33  A: 

It looks to me like you really want to print out the names of each enum, rather than the values. In which case Enum.GetNames seems to be the right approach.

public enum Suits
{
        Spades,
        Hearts,
        Clubs,
        Diamonds,
        NumSuits
}

public void PrintAllSuits()
{
        foreach(string name in Enum.GetNames(typeof(Suits)))
        {
                System.Console.WriteLine(suit);
        }
}

By the way, incrementing the value is not a good way to enumerate the values of an enum. You should do this instead.

I would use Enum.GetValues(typeof(Suit)) instead.

public enum Suits
{
        Spades,
        Hearts,
        Clubs,
        Diamonds,
        NumSuits
}

public void PrintAllSuits()
{
        foreach(var suit in Enum.GetValues(typeof(Suits)))
        {
                System.Console.WriteLine(suit.ToString());
        }
}
Haacked
What does the "var" in "var suit" mean? i'm not familiar with that syntax.
Ian Boyd
var is a new keyword in C# 3.0 (.NET 3.5) that says I don't feel like typing out the type of this variable (or don't know it), I want the compiler to infer it for me. You can only use it with assignment in the same statement as the declaration.
Mike Brown
@Mike Brown: Hmmm, unknown variable types. Sounds like we're going back to the dark days of typeless and variant languages. *shiver*
Ian Boyd
The variable is still typed in the same way as other variables. It's just that you allow the compiler to infer the type from the RHS of the assignment (it can only be used with assignments, you can't just do `var foo;`). This is particularly important with LINQ, as the returned types can be quite complex, and not easy to work out yourself.
Matt Sach
@Matt Sach: It's fine as long as the type inferred by the compiler is the type i inferred when i wrote it.
Ian Boyd
+5  A: 

Also I believe you're supposed to call it "Suit" not "Suits", unless you're going to be bitwise or-ing the values together, which you probably aren't, since suits themselves are mutually exclusive.

Kevin Conner
i'm back and forth on that. But i changed the OP to singular.
Ian Boyd
A: 
public void PrintAllSuits()
 {
  foreach(string suit in Enum.GetNames(typeof(Suits)))
  {
   Console.WriteLine(suit);
  }
 }
Joshua Drake
That enumerates a string, don't forget to convert those things back to an enumeration value so the enumeration can be enumerated.
Ian Boyd
I see from your edit that you want to actually operate on the enums themselves, the above code addressed your original post.
Joshua Drake
A: 

it works with

foreach (string _name in Enum.GetNames(typeof(Suits)) { ... }
That enumerates a string; don't forget in the loop to conver the string to a Suit.
Ian Boyd
+25  A: 

I made some extensions for easy enum usage, maybe someone can use it...

//
// Author: Bob Maes <[email protected]>
//

public static class EnumExtensions
{
    /// <summary>
    /// Gets all items for an enum value.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="value">The value.</param>
    /// <returns></returns>
    public static IEnumerable<T> GetAllItems<T>(this Enum value)
    {
        foreach (object item in Enum.GetValues(typeof(T)))
        {
            yield return (T)item;
        }
    }

    /// <summary>
    /// Gets all items for an enum type.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="value">The value.</param>
    /// <returns></returns>
    public static IEnumerable<T> GetAllItems<T>() where T : struct
    {
        foreach (object item in Enum.GetValues(typeof(T)))
        {
            yield return (T)item;
        }
    }

    /// <summary>
    /// Gets all combined items from an enum value.
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <param name="value">The value.</param>
    /// <returns></returns>
    public static IEnumerable<T> GetAllSelectedItems<T>(this Enum value)
    {
        int valueAsInt = Convert.ToInt32(value, CultureInfo.InvariantCulture);

        foreach (object item in Enum.GetValues(typeof(T)))
        {
            int itemAsInt = Convert.ToInt32(item, CultureInfo.InvariantCulture);

            if (itemAsInt == (valueAsInt & itemAsInt))
            {
                yield return (T)item;
            }
        }
    }

    /// <summary>
    /// Determines whether the enum value contains a specific value.
    /// </summary>
    /// <param name="value">The value.</param>
    /// <param name="request">The request.</param>
    /// <returns>
    ///     <c>true</c> if value contains the specified value; otherwise, <c>false</c>.
    /// </returns>
    public static bool Contains<T>(this Enum value, T request)
    {
        int valueAsInt = Convert.ToInt32(value, CultureInfo.InvariantCulture);
        int requestAsInt = Convert.ToInt32(request, CultureInfo.InvariantCulture);

        if (requestAsInt == (valueAsInt & requestAsInt))
        {
            return true;
        }

        return false;
    }
}

The enum itself must be decorated with the FlagsAttribute

[Flags]
public enum EnumExample
{
    ValueA = 1,
    ValueB = 2,
    ValueC = 4,
    ValueD = 8,
    Combi = ValueA | ValueB
}
bob
+1 for the effort.
Ikke
+1 lots of useful info, and the extensions.
Maslow
how to use these extensions ?
Khalil Dahab
A one liner for the first extension method; it's no more lazy.return Enum.GetValues(typeof(T)).Cast<T>();
Leyu
+7  A: 

The .NET compact framework does not support Enum.GetValues. Here's a good workaround from Ideas 2.0: Enum.GetValues in Compact Framework:

public IEnumerable<Enum> GetValues(Enum enumeration)
{
   List<Enum> enumerations = new List<Enum>();
   foreach (FieldInfo fieldInfo in enumeration.GetType().GetFields(
         BindingFlags.Static | BindingFlags.Public))
   {
      enumerations.Add((Enum)fieldInfo.GetValue(enumeration));
   }
   return enumerations;
}
Ekevoo
Nice addition - just what I was looking for :-)
skolima
This is also a good solution if you're working with Silverlight like I am :)
Darko Z
A: 
> foreach (Suit suit in Enum.GetValues(typeof(Suit))) { }

I've heard vague rumours that this is terifically slow. Anyone know? – Orion Edwards Oct 15 '08 at 1:31 7

I think caching the array would speed it up considerably. It looks like you're getting a new array (through reflection) every time. Rather:

Array ar = Enum.GetValues(typeof(Suit));
foreach(Suit temp_suit in ar) Do_Something(temp_suit);

That's at least a little faster, ja?

Limited Atonement
A: 

Just to add my solution, which works in compact framework (3.5) and supports Type checking at compile time:

public static List<T> getEnumValues<T>() where T : new() {
    T valueType = new T();
    return typeof(T).GetFields()
        .Select(fieldInfo => (T)fieldInfo.GetValue(valueType))
        .Distinct()
        .ToList();
}

public static List<String> getEnumNames<T>() {
    return typeof (T).GetFields()
        .Select(info => info.Name)
        .Distinct()
        .ToList();
}

- If anyone knows how to get rid of the "T valueType = new T()", I'd be happy to see a solution.

A call would look like this:

List<MyEnum> result = Utils.getEnumValues<MyEnum>();
Mallox
what about using `T valueType = default(T)`?
Oliver
Great, I didn't even know that keyword. Always nice to learn something new. Thank you!Does it always return a reference to the same object, or does it create a new instance each time the default statement is called?I haven't found anything on the net about this so far, but if it creates a new instance every time, it kind of defeats the purpose I was looking for (having a one-liner ^^).
Mallox
A: 

Another way to do this : for (int i = 0; i < 4; i++) { Suit suit = (Suit)i; DoSomething(suit); } But I'm not sure if it's better.

Ota
-1: If the Suit enumeration changes, `i < 4` will need to be adjusted to match the number of possible values. Hard to maintain with a cast that could be avoided with one of the other solutions.
FreshCode