Reputation: 11
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 ?
Upvotes: 1
Views: 1007
Reputation: 1280
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;
}
}
}
Upvotes: 0
Reputation: 887777
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.
Upvotes: 2