C# 4.0 使用枚举方法将泛型方法约束为
我一直在尝试为标记的枚举值编写实用程序扩展方法。此方法的目的是检索当前启用的所有标志的列表 我想做的是:C# 4.0 使用枚举方法将泛型方法约束为,c#-4.0,enums,extension-methods,C# 4.0,Enums,Extension Methods,我一直在尝试为标记的枚举值编写实用程序扩展方法。此方法的目的是检索当前启用的所有标志的列表 我想做的是: public static IEnumerable<T> GetFlags<T>(this T value) where T:Enum { return Enum.GetValues(typeof(T)).OfType<Enum>().Where(value.HasFlag).Cast<T>(); } 公共静态IEnu
public static IEnumerable<T> GetFlags<T>(this T value) where T:Enum
{
return Enum.GetValues(typeof(T)).OfType<Enum>().Where(value.HasFlag).Cast<T>();
}
公共静态IEnumerable GetFlags(此T值),其中T:Enum
{
返回类型()的Enum.GetValues(typeof(T))。其中(value.HasFlag.Cast();
}
但是,由于泛型不适用于枚举类型,我不得不采取以下措施:
public static IEnumerable<T> GetFlags<T>(this Enum value)
{
return Enum.GetValues(typeof(T)).OfType<Enum>().Where(value.HasFlag).Cast<T>();
}
公共静态IEnumerable GetFlags(此枚举值)
{
返回类型()的Enum.GetValues(typeof(T))。其中(value.HasFlag.Cast();
}
有没有办法绕过这个问题,或者我应该在每次调用方法时显式地声明类型?最好的方法是
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")
公共抽象类枚举,其中Temp:class{
公共静态TEnum解析(字符串名称),其中TEnum:struct,Temp{
return(TEnum)Enum.Parse(typeof(TEnum),name);
}
}
公共抽象类枚举:枚举{}
解析(“本地”)
如果愿意,可以将Temp
设置为Enum
,为Enum
提供一个私有构造函数和一个公共嵌套的抽象继承类,以防止非Enum的继承版本
您不能使用此技巧生成扩展方法,因为扩展方法必须在
静态类中定义,并且不能继承其他类。我使用反射。您只需在运行时自己调用HasFlag
(或任何您需要的方法)
where
子句提供了尽可能多的约束。然后,如果您的类型不是enum
,则此代码将引发targetingException
/// <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;
}
}
}
//
///获取给定枚举值的标志。
///
///枚举类型
///枚举值。
///标记的值。
公共静态IEnumerable GetFlags(此枚举值)
其中T:struct
{
类型enumType=enumValue.GetType();
foreach(枚举中的T值。GetValues(枚举类型))
{
bool hasFlag=(bool)enumType.InvokeMember(“hasFlag”,BindingFlags.InvokeMethod,null,enumValue,新对象[]{value});
如果(hasFlag)
{
收益回报值;
}
}
}
它的可能复制品没有其他替代品那么难看。实际上,相当巧妙。