我有以下代码:
[Flags()]
public enum Foo
{
Unknown = 0x00,
A = 0x01,
B = 0x02,
C = 0x04,
D = 0x08,
}
public static class Extensions
{
public static List<Foo> AsList(this Foo types)
{
List<Foo> list = new List<Foo>();
foreach(Foo sT in Enum.GetValues(typeof(Foo)))
{
if ((sT & types) == sT) list.Add(sT);
}
return list;
}
}
class Program
{
static void Main(string[] args)
{
Foo foo1 = Foo.A | Foo.B | Foo.C;
Foo foo2 = Foo.C | Foo.B;
Foo firstInfoo1 = foo1.AsList()[0];
Foo firstInFoo2 = foo2.AsList()[0];
}
}
现在firstInfoo1
和firstInfoo2
都是Unknown
我不想要的。看到那里的代码应该总是返回索引[1],如下所示:foo1.AsList()[1]
?
这是个好主意吗?关于错误的任何想法,绑定检查都需要完成。
另外我们来看看foo2,我先添加Foo.C
,然后添加Foo.B
秒。有什么方法可以从AsList Foo.C
而不是Foo.B
获得,即第一个按顺序添加。
这可能吗?
感谢帮助。
由于
答案 0 :(得分:2)
删除未知值,或执行以下操作:
if ((int)sT != 0 && (sT & types) == sT) list.Add(sT);
一些背景:那些OR-ed枚举不像存储器那样存储,它们存储为一个简单的整数,因此.NET不知道如何构造枚举。
答案 1 :(得分:1)
您需要具体排除Foo.Unknown
元素,因为0 & x
始终为0
if ((sT != Foo.Unknown) && ((sT & types) == sT)) list.Add(sT);
无法保留枚举的顺序。您必须使用其他类型才能执行此操作(List<Foo>
?)。
答案 2 :(得分:1)
您的“AsList”实现中有一些要点(如果您打算添加类似的内容) 更多枚举的扩展名:
删除所有别名
是个好主意例如,对于某些枚举:
public enum Quantity { Zero = 0, // <- You probably want to preserve it One = 1, Many = 2, ALotOf = 2 // <- You'd rather eliminate this alias }
另一个
[Flags]
public enum Rigths {
None = 0, // <- You don't need it
CanRead = 1,
CanWrite = 2,
CanDelete = 4,
CanErase = 4, // <- This alias is of no use
CanEliminate = 4 // <- And this alias is of no use as well
}
可能的解决方案是
public static class Extensions {
private static long EnumToLong(Object value) {
if (Object.ReferenceEquals(null, value))
return 0;
Type type = value.GetType();
if (!type.IsEnum)
return 0;
Type baseType = Enum.GetUnderlyingType(type);
if (baseType == typeof(long))
return (long) (value);
else if (baseType == typeof(ulong))
return (long) ((ulong) value);
else if (baseType == typeof(uint))
return (long) ((uint) value);
else if (baseType == typeof(int))
return (long) ((int) value);
else if (baseType == typeof(short))
return (long) ((short) value);
else if (baseType == typeof(ushort))
return (long) ((ushort) value);
else if (baseType == typeof(byte))
return (long) ((byte) value);
else if (baseType == typeof(sbyte))
return (long) ((sbyte) value);
return 0;
}
private static List<T> CoreAsList<T>(Enum value) {
// Has [Flags] attribute?
Boolean hasFlagAttribute = false;
Object[] attrs = typeof(T).GetCustomAttributes(true);
for (int i = attrs.GetLowerBound(0); i <= attrs.GetUpperBound(0); ++i)
if (attrs[i] is FlagsAttribute) {
hasFlagAttribute = true;
break;
}
List<T> result = new List<T>();
HashSet<long> hs = new HashSet<long>();
foreach (var item in Enum.GetValues(typeof(T))) {
long v = EnumToLong(item);
long all = EnumToLong(value);
if (hs.Contains(v))
continue;
hs.Add(v);
if ((all & v) == v)
if (Enum.IsDefined(typeof(T), item))
if (!((v == 0) && (hasFlagAttribute)))
result.Add((T) item);
}
return result;
}
/// <summary>
/// You extension
/// </summary>
public static List<Foo> AsList(this Foo types) {
return CoreAsList<Foo>(types);
}
}
至于订单,你不能保留它。如您所见,枚举实际上是一个整数:
[Flags]
public enum Options: long { // or byte, int, uint, short…
Option1 = 0,
Option2 = 1,
OptionN = 1024
}
什么时候你做的事情
Options a = b | c
你因为整数而失去了订单
b | c == c | b