我已经为我的问题寻找解决方案,但到目前为止我无法弄清楚如何做到这一点。
我需要获取由enum
值标记的int
值的列表。
我能够在特定情况下执行此操作,但我想为通用枚举器创建通用函数。
具体案例的代码是:
IList<MyEnum> EnumList= new List<MyEnum>();
MyEnum EnumIUseToFlag= (MyEnum)intToParse;
foreach (MyEnumitem in Enum.GetValues(typeof(MyEnum)))
{
if (EnumIUseToFlag.HasFlag(item))
{
EnumList.Add(item);
}
}
现在,对于通用方法,我尝试的是:
public static IList<T> GetFlaggedValues<T>(int intValue) where T : struct, IConvertible
{
if (!typeof(T).IsEnum)
{
throw new ArgumentException("T must be an enumerated type");
}
IList<T> listToReturn = new List<T>();
Enum enumToParse = Enum.Parse(typeof(T), intValue.ToString()) as Enum;
foreach (T item in Enum.GetValues(typeof(T)))
{
// here I am not able to cast item in the integer
//values i need to use in order to flag my enum
}
return listToReturn;
}
答案 0 :(得分:2)
简单的回答是 - 不要使用泛型。这个问题不需要。使用良好的旧继承并将标志作为System.Enum
传递,这是所有枚举的基类。
public static IList<Enum> GetFlaggedValues(Enum flag)
{
return Enum
.GetValues(flag.GetType())
.Cast<Enum>()
.Where(e => e.HasFlag(flag))
.ToList();
}
这是一个简单的测试:
enum MyEnum
{
Red = 0xF00,
Orange = 0xFF0,
Yellow = 0x0F0,
Green = 0x0FF,
Blue = 0x00F,
Purple = 0xF0F
}
public static void Main()
{
var list = GetFlaggedValues(MyEnum.Blue);
foreach (var e in list)
{
Console.WriteLine(e);
}
}
输出:
Blue
Green
Purple
由于我们使用Enum
基类型的方式,不可能使用非枚举参数调用此方法,因此不需要进行混乱的验证检查并抛出异常。不能用c#中的泛型来做到这一点。
另一方面,回复类型为List<Enum>
而不是List<MyEnum>
可能会让您感到困扰。精细。如果你坚持使用结果集的强类型列表,你可以来回投射,如下所示:
public static IList<T> GetFlaggedValues<T>(T input) where T : struct, IConvertible
{
Enum flag = input as Enum;
if (flag == null) return new List<T>();
return Enum
.GetValues(typeof(T))
.Cast<Enum>()
.Where(e => e.HasFlag(flag))
.Cast<T>()
.ToList();
}
注意在最后一个例子中,如果输入实际上不是枚举,我只返回一个空列表,这似乎是合理的行为,因为它准确地反映了枚举中的哪些值匹配 - 没有一个。但如果您愿意,可以抛出异常。
另外,您可能已经注意到我更改了原型,以便您可以传递枚举本身而不是整数。这允许编译器推断类型,因此您只需调用
var list = GetFlaggedValues(MyEnum.Blue);
而不必输入
var list = GetFlaggedValues<MyEnum>((int)MyEnum.Blue); //Ugly
如果你想传递一个整数,你总是可以投射它,如下所示:
var list = GetFlaggedValues((MyEnum)0xF0F);
...编译器会推断出<MyEnum>
位。
答案 1 :(得分:0)
这对你有用:
public static IList<T> GetFlaggedValues<T>(ulong intValue) where T : struct
{
if (!typeof(T).IsEnum)
{
throw new ArgumentException("T must be an enumerated type");
}
var flagAttrib = Attribute.GetCustomAttribute(typeof(T), typeof(FlagsAttribute));
if(flagAttrib==null)
{
throw new ArgumentException("T must have [Flags] attribute.");
}
List<T> vals = new List<T>();
foreach (var e in Enum.GetValues(typeof(T)))
{
var item = Convert.ToUInt64(e);
if ((item & intValue) != 0)
vals.Add((T)Enum.ToObject(typeof(T), item));
}
return vals;
}
答案 2 :(得分:0)
在foreach中你可以添加下一行:
var itemAsEnumValue = (Enum)Enum.Parse(typeof(T), item.ToString());
if (enumToParse.HasFlag(itemAsEnumValue))
{
listToReturn.Add(item);
}