3

There are several situations where I want to have an IEnumerable<MyEnum> of enum values. The code I normally use looks like this:

Enum.GetValues(typeof(MyEnum)).OfType<MyEnum>()

But not only is it not very pretty to look at, most people will need a couple of seconds to understand what it does. It's also a huge pain to write, especially when you need it on multiple occasions throughout the code.

To make my life easier, I've decided to write an extension method like this:

public static IEnumerable<T> GetValues<T>(this T e) where T : Enum
{
    return Enum.GetValues(typeof(T)).OfType<T>();
}

Except I have to get rid of the where T : Enum part, because "Constraint cannot be special class 'Enum'". Also, it's not exactly what I want, because instead of MyEnum.GetValues() I'd need to write MyEnum.Value.GetValues(), which is quite confusing and not very pretty either.

Which leads me to this question: Is there a better way to get an IEnumerable<MyEnum> of enum values than using Enum.GetValues()?

Do I really have no other choice but to make it Helper.GetEnumValues<MyEnum>()?

If possible, I'd like a solution that works in Unity, but any solution would be appreciated either way.

Nolonar
  • 5,962
  • 3
  • 36
  • 55
  • "most people will need a couple of seconds to understand what it does" why do you say that? It's perfectly understandable to me. I'm not trying to be cocky; my point is: there is a wide range of experience among developers. You shouldn't worry about what other developers might think, as long as you're writing reasonably-short statements. It's their burden to understand it. If you really think it's not clear, you could always adorn it with a comment. – rory.ap Nov 02 '16 at 23:27
  • If you rename `Helper` to `Enums` and `GetEnumValues` to `For`, it becomes shorter and self-documenting: `var firstEnum = Enums.For().first(); – Paul Hicks Nov 03 '16 at 00:26
  • Eleven different answers in the marked duplicate, and most if not all essentially being to call `GetValues()`, suggests that's as good as it gets. I would use `Cast()` instead of `OfType()` -- the former is more like a regular cast, while the latter is more like using the `as` operator -- but there aren't built-in options better than this. See, however, http://stackoverflow.com/a/2632759 for a solution that actually _does_ constrain the method call to enum types. – Peter Duniho Nov 03 '16 at 00:27
  • I'll point out that at the very least, you don't need to use extension method syntax if you don't want. If it's "not pretty", then just write `EnumExtensionClass.GetValues(T e)` (shorten `EnumExtensionClass` to whatever you like, of course). – Peter Duniho Nov 03 '16 at 00:27
  • If you do like the extension method syntax, you don't need to care what you extend. This is equivalent: `public static IEnumerable EnumValues(this object unused) where T : struct { return Enum.GetValues(typeof(T)).OfType(); }` Now you can call `this.EnumValues()` almost anywhere: `this` is unused :) – Paul Hicks Nov 03 '16 at 00:29
  • You can use `Enum.GetValues()` if you define the following static class in your namespace: `public static class Enum { public static IEnumerable GetValues() => Enum.GetValues(typeof(T)).Cast(); }` _(You can also use the opportunity to create cache-backed versions of this frequently used `Enum` methods if you're finding them to be a bottleneck.)_ – Alain Apr 16 '20 at 23:40

1 Answers1

3

This is the perfect solution. .Net does not offer a strongly-typed Enum.GetValues at this time. People will only take a few seconds to understand what this does because one would expect .Net to offer a strongly-typed enumeration of Enums of one type right now.

You're using GetValues correctly as MSDN suggests.

Khelvaster
  • 852
  • 1
  • 6
  • 18