Jonathan Wood
Jonathan Wood

Reputation: 67193

Using Where on Enum Values

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?

Upvotes: 2

Views: 1163

Answers (3)

Ivan Stoev
Ivan Stoev

Reputation: 205589

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));

Upvotes: 3

esmoore68
esmoore68

Reputation: 1296

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));

Upvotes: 1

Yacoub Massad
Yacoub Massad

Reputation: 27861

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.

Upvotes: 4

Related Questions