2

I have defined an enum with the [Flag] attribute.

Given an integer value, I would like to print all the enum values for the bits set in the integer value.

Here's what I have so far.

string s = string.Join(", ", Enum.GetValues(typeof(MyEnumType)).OfType<Enum>()
                                 .Where(x => (MyIntValue & (int)x) != 0));

But the typecast to int in the last line gives me the following error.

Cannot convert type 'System.Enum' to 'int'

I wish Microsoft would replace all the Framework code that returns Array in favor of types that support LINQ.

But is there an easy way to do this?

7
  • 1
    Why don't do .OfType<MyEnumType>() instead of .OfType<Enum>()? Commented May 12, 2016 at 19:40
  • casting your int value to the Enum and calling ToString() should do exactly what you want. See stackoverflow.com/questions/8447/… Commented May 12, 2016 at 19:48
  • "I wish Microsoft would replace all the Framework code that returns Array in favor of types that support LINQ." - and what should they do about all of the legacy code that was written before Linq? Just let all that code developed over the years suddenly break? Commented May 12, 2016 at 19:49
  • BTW, Arrays support Linq just fine as they implement IEnumerable<T> as well as IEnumerable. Commented May 12, 2016 at 19:51
  • @DStanley Uh, Microsoft updates the Framework all the time. They can do it so it doesn't break code. Create a new class to do the work. There are endless ways. Why would you assume I am asking Microsoft to break all the existing code? Commented May 12, 2016 at 20:06

3 Answers 3

4

Casting to MyEnumType instead of the generic Enum should fix the problem:

string s = string.Join(
    ", ",
    Enum.GetValues(typeof(MyEnumType))
        .OfType<MyEnumType>()
        .Where(x => (MyIntValue & (int)x) != 0));

You should really be using Cast instead of OfType since you are sure that the items are of type MyEnumType.

Sign up to request clarification or add additional context in comments.

4 Comments

Yeah, you're right. This code is still too messy and executes too slow. Microsoft needs to update the Framework. Thanks.
@JonathanWood Which part executes "too slow" and how do you propose that Microsoft fix it?
I read OfType() can impact performance. What if Enum.GetValues() returned List<T>, where T was my enum type? That would be so much more natural, particularly when using LINQ. The problem is that these routines were written before generics. That's why I think they should be rewritten.
I think Cast<MyEnumType> should be slightly faster because it doesn't filter (and filtering isn't necessary). But what is slow? Does the enum type have so many values that this becomes noticeably slow?
3

Too much LINQ way of thinking, so sometimes we forget where we come from:) Starting from the very first .NET version, Enum.GetValues(typeof(MyEnum)) actually returns MyEnum[], so what you need is neither OfType, nor Cast, but simple C# cast:

string s = string.Join(", ", ((MyEnum[])Enum.GetValues(typeof(MyEnumType)))
    .Where(x => (MyIntValue & (int)x) != 0));

Since that typeof combined with the casting to the same type is quite annoying, from a very long time I have this little helper in my pocket:

public static class EnumInfo
{
    public static T[] GetValues<T>() where T : struct // I (and not only) wish I could say where T : enum
    {
        return (T[])Enum.GetValues(typeof(T));
    }
}

which allows me to use much more concise

string s = string.Join(", ", EnumInfo.GetValues<MyEnumType>()
    .Where(x => (MyIntValue & (int)x) != 0));

2 Comments

Shouldn't your GetValues() method return something other than T? For example, T[]?
@JonathanWood Absolutely, thank you (you know how it is when you write the code directly in the browser:)
1

You can write your own GetValues method that uses generics to get what you need:

public static class EnumUtil
{
    public static IEnumerable<T> GetValues<T>()
    {
        foreach(T enumVal in Enum.GetValues(typeof(T)))
        {
            yield return enumVal;
        }
    }
} 

Which is then used like so:

var s = string.Join(", ", EnumUtil.GetValues<TestEnum>()
    .Where(x => (myIntValue & (int)x) != 0));

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.