How to loop through all enum values in C#? [duplicate]
Asked Answered
C

8

1749

This question already has an answer here:
How do I enumerate an enum in C#? 26 answers

public enum Foos
{
    A,
    B,
    C
}

Is there a way to loop through the possible values of Foos?

Basically?

foreach(Foo in Foos)
Continuo answered 9/6, 2009 at 20:25 Comment(0)
L
2485

Yes you can use the ‍GetValue‍‍‍s method:

var values = Enum.GetValues(typeof(Foos));

Or the typed version:

var values = Enum.GetValues(typeof(Foos)).Cast<Foos>();

I long ago added a helper function to my private library for just such an occasion:

public static class EnumUtil {
    public static IEnumerable<T> GetValues<T>() {
        return Enum.GetValues(typeof(T)).Cast<T>();
    }
}

Usage:

var values = EnumUtil.GetValues<Foos>();
Leralerch answered 9/6, 2009 at 20:28 Comment(15)
You can cast the array directly: (T[])Enum.GetValues(typeof(T))Imperceptible
The good thing about @ŞafakGür's comment is that (1) you don't have to go through an extra iterator (.Cast<Foos>), and (2) you don't need to box all the values and unbox them again. Şafak's cast will remain valid as long as they don't change the array type returned to some other type (like object[]). But we can be completely sure they won't because (a) it would lose performance, (b) there are already millions of codelines using Şafak's cast, and they would all break with a runtime exception.Dibbell
Of course, how many enums are going to contain more than a dozen or two values? I imagine that in most cases boxing/unboxing is a negligible hit, so the cleanest solution is the highest priority.Clay
@JCoombs I find this clean enough: public static IReadOnlyList<T> GetValues<T>() { return (T[])Enum.GetValues(typeof(T)); }. But yeah, performance difference is negligible in common usage. I just don't like the idea of creating an iterator when I already have an iterable (enumerable) object to return.Imperceptible
Unfortunately, this does not answer the question posed. The question was how to loop through the values of an enum. SLaks answered the question.Pesky
@JAB, I think it basically answers it, just somewhat implicitly. Instead of the original "Foos" we'd have foreach (var v in values)Clay
When I add the cast (Foos[]), my code run 1,6 times faster. Try it yourself. I tested an empty foreach with StopWatch. for (int i = 0; i < 1000000; i++) foreach (Foos f in (Foos[])Enum.GetValues(typeof(Foos))) {}Compute
By casting to an array you are depending on an implementation detail that is subject to change. If Microsoft in the future implements it without an array, your code crashes. If performance is such an issue then you should just cache the results.Heredes
@MarkSowul Read the third comment. Great Jon Skeet also uses it (link). Microsoft will not dare change it.Compute
I stand by my comment. If performance is such an issue, you should cache the results. I bet if you actually are calling this function so many times that it's a hot path, it's a situation where you are doing a lookup, and you would get significantly better performance by caching the result to a HashSet. "Microsoft won't change it because we're all already misusing it" is a poor excuse. en.wikipedia.org/wiki/Tragedy_of_the_commonsHeredes
If I want to get the enum number values as list or array then how to use the getValues method?Vaish
@MarkSowul I read the article Tragedy of the commons and failed to understand how it relates to your comment/the discussion. Would you mind to explain it?Niche
@Niche As an example, let's say that Microsoft did want to optimize Enum.GetValues to return something other than an array (maybe they can point to some internal structure to avoid duplicating, or something). Well, the individual users who have acted according to their own self-interest, by depending on implementation details and saying "Microsoft won't change it because of all the people like me who didn't adhere to the API contract", ruins it for everyone else, because now Microsoft can't change it and everyone else can't benefit from the optimizations.Heredes
I perhaps should have used "negative externality" rather than "tragedy of the commons", but e.g. "The commons dilemma is a specific class of social dilemma in which people's short-term selfish interests are at odds with long-term group interests and the common good." (en.wikipedia.org/wiki/Tragedy_of_the_commons#Commons_dilemma)Heredes
As of C# 7.3, you can (and probably should) constrain the extension method with where T : EnumOmmatidium
S
938
foreach(Foos foo in Enum.GetValues(typeof(Foos)))
Saturninasaturnine answered 9/6, 2009 at 20:28 Comment(5)
This is a great solution. By using "Foos" instead of "var" the type inference system was able to use the right version of GetValues which returned the correct object type. Nice!Ure
@RobertPatterson By using Foos nothing is magically inferred. It is an explicit cast.Snivel
@daveD I'd like to think people can handle writing a foreach block on their own.Visit
@RobertPatterson var works here, in 2019.Critical
that is very goodFibrilla
A
152
foreach (EMyEnum val in Enum.GetValues(typeof(EMyEnum)))
{
   Console.WriteLine(val);
}

Credit to Jon Skeet here: http://bytes.com/groups/net-c/266447-how-loop-each-items-enum

Acculturation answered 9/6, 2009 at 20:28 Comment(0)
H
71
foreach (Foos foo in Enum.GetValues(typeof(Foos)))
{
    ...
}
Hoyden answered 9/6, 2009 at 20:29 Comment(1)
Repeative answer dear @arianYentai
M
46

UPDATED
Some time on, I see a comment that brings me back to my old answer, and I think I'd do it differently now. These days I'd write:

private static IEnumerable<T> GetEnumValues<T>()
{
    // Can't use type constraints on value types, so have to do check like this
    if (typeof(T).BaseType != typeof(Enum))
    {
        throw new ArgumentException("T must be of type System.Enum");
    }

    return Enum.GetValues(typeof(T)).Cast<T>();
}
Monah answered 9/6, 2009 at 20:30 Comment(5)
Why is using LINQ "more correct"? Please c.f. You can cast the array directly: (T[])Enum.GetValues(typeof(T)) @SafakGür, this version has less overhead IMO.Dday
make it simple GetEnumValues<T>() where T : EnumDemonstrable
@SaboorAwan is not possible to use System.Enum as a type parameter constraint. Compiler says: Constraint cannot be special class 'Enum'Limelight
Yes that's why I have that comment and type checking thing in my implementation; I'd already thought of that. :)Monah
Quick note. In C# 7.3 you can now use Enum (as well as unmanaged and delegate) as generic constraints.Baudin
M
40
static void Main(string[] args)
{
    foreach (int value in Enum.GetValues(typeof(DaysOfWeek)))
    {
        Console.WriteLine(((DaysOfWeek)value).ToString());
    }

    foreach (string value in Enum.GetNames(typeof(DaysOfWeek)))
    {
        Console.WriteLine(value);
    }
    Console.ReadLine();
}

public enum DaysOfWeek
{
    monday,
    tuesday,
    wednesday
}
Monia answered 9/6, 2009 at 20:32 Comment(0)
M
16

Yes. Use GetValues() method in System.Enum class.

Misbecome answered 9/6, 2009 at 20:28 Comment(1)
And if you're using .net5, it comes with a generic version out of the box. i.e. no more typeof() and casting required as per most of the above examples. https://mcmap.net/q/27014/-how-to-enumerate-an-enumMelise
G
14
 Enum.GetValues(typeof(Foos))
Gatling answered 9/6, 2009 at 20:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.