1

I've been trying to write a utility extension method for flagged enum values. The purpose with this method is to retrieve a list of all the flags that are currently enabled.

What I wanted to do was this:

 public static IEnumerable<T> GetFlags<T>(this T value) where T:Enum 
 {
 return Enum.GetValues(typeof(T)).OfType<Enum>().Where(value.HasFlag).Cast<T>(); 
 }

However, since generics doesn't work with the Enum type I had to resort to the following:

public static IEnumerable<T> GetFlags<T>(this Enum value) 
 {
 return Enum.GetValues(typeof(T)).OfType<Enum>().Where(value.HasFlag).Cast<T>(); 
 }

Is there any way to get around this or should I resign myself to explicitly having to declare the type every time the method is called ?

asked Feb 9, 2011 at 15:43
2

2 Answers 2

2

The best you can do is where T : struct.

For non-extension methods, you can use an ugly trick:

public abstract class Enums<Temp> where Temp : class {
 public static TEnum Parse<TEnum>(string name) where TEnum : struct, Temp {
 return (TEnum)Enum.Parse(typeof(TEnum), name); 
 }
}
public abstract class Enums : Enums<Enum> { }
Enums.Parse<DateTimeKind>("Local")

If you want to, you can give Enums<Temp> a private constructor and a public nested abstract inherited class with Temp as Enum, to prevent inherited versions for non-enums.

You can't use this trick to make extension methods because extension methods must be defined in a static class and cannot inherit a different class.

answered Feb 9, 2011 at 15:49
Sign up to request clarification or add additional context in comments.

1 Comment

It's not as ugly as some of the alternatives out there. Pretty ingenious, actually.
0

I use reflection. Just invoke the HasFlag (or whatever method you need) by yourself at runtime.

The where clause gives as much constraint as we can. Then, if your type is not an enum, this code will raise a TargetInvocationException.

/// <summary>
/// Gets the flags for the given enum value.
/// </summary>
/// <typeparam name="T">The enum type</typeparam>
/// <param name="enumValue">The enum value.</param>
/// <returns>The flagged values.</returns>
public static IEnumerable<T> GetFlags<T>(this T enumValue)
 where T : struct
{
 Type enumType = enumValue.GetType();
 foreach (T value in Enum.GetValues(enumType))
 {
 bool hasFlag = (bool)enumType.InvokeMember("HasFlag", BindingFlags.InvokeMethod, null, enumValue, new object[] { value });
 if (hasFlag)
 {
 yield return value;
 }
 }
}
answered Jul 25, 2012 at 12:21

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.