我一直在尝试为标记的枚举值编写实用程序扩展方法。此方法的目的是检索当前启用的所有标志的列表。
我想做的是:
public static IEnumerable<T> GetFlags<T>(this T value) where T:Enum
{
return Enum.GetValues(typeof(T)).OfType<Enum>().Where(value.HasFlag).Cast<T>();
}
但是,由于泛型无法与Enum类型一起使用,因此我不得不采用以下方法:
public static IEnumerable<T> GetFlags<T>(this Enum value)
{
return Enum.GetValues(typeof(T)).OfType<Enum>().Where(value.HasFlag).Cast<T>();
}
有没有什么方法可以解决这个问题,或者我是否应该在每次调用方法时明确要求声明类型?
答案 0 :(得分:2)
您可以做的最好的事情是where T : struct
。
对于非扩展方法,您可以使用一个丑陋的技巧:
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")
如果您愿意,可以将Enums<Temp>
私有构造函数和公共嵌套抽象继承类Temp
作为Enum
,以防止非枚举的继承版本。
您不能使用此技巧来制作扩展方法,因为扩展方法必须在static
类中定义,并且不能继承其他类。
答案 1 :(得分:0)
我使用反射。只需在运行时自行调用HasFlag
(或任何你需要的方法)。
where
子句给出了尽可能多的约束。然后,如果您的类型不是enum
,则此代码将引发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;
}
}
}