鉴于enum
:
[Flags]
public enum mytest
{
a = 1,
b = 2,
c = 4
}
我想出了两种方法来表示单个变量中的所有值:
var OR1 = (mytest)Enum.GetNames(typeof(mytest)).Sum(a => (int)Enum.Parse(typeof(mytest), a));
var OR2 = (mytest)(typeof(mytest).GetEnumValues() as mytest[]).Sum(a => (int)a);
现在,虽然它们都有效,但还有更简洁的方法吗?可能是我失踪的.NET方法?
编辑:为了澄清,我需要将该函数设置为动态 - 我不想通过指定每个enum
值来计算它。
答案 0 :(得分:20)
如果拥有All
成员是有意义的,只需直接提供:
[Flags]
public enum mytest
{
a = 1,
b = 2,
c = 4,
All = 7
}
尽管如此,写一些更惯用的方式可能是:
[Flags]
public enum MyTest
{
A = 1,
B = 1 << 0x01,
C = 1 << 0x02,
All = A | B | C
}
这显示了枚举值的逻辑进展,并且在All
情况下,可以轻松添加其他成员。
答案 1 :(得分:14)
使用Enumerable.Aggregate()
按位或一起使用它们。即使您具有表示多个设置位的枚举值,这也将起作用,而不是Sum()
。
var myTestValues = (MyTest[]) typeof(MyTest).GetEnumValues();
var sum = myTestValues.Aggregate((a, b) => a | b);
sum.Dump();
使这个泛型变得有点棘手,因为你不能将泛型类型约束为枚举,原始类型也不能彼此有任何子类型关系。我能想出的最好的假设基础类型是int
,它在大多数情况下都应该足够好:
TEnum AllEnums<TEnum>()
{
var values = typeof(TEnum).GetEnumValues().Cast<int>();
return (TEnum) (object) values.Aggregate((a,b) => a|b);
}
答案 2 :(得分:6)
对于通用方法,请使用Linq的Enumerable.Aggregate扩展方法;
var flags = Enum.GetValues(typeof(mytest))
.Cast<int>()
.Aggregate(0, (s, f) => s | f);
或者在包装方法中
TEnum GetAll<TEnum>() where TEnum : struct
{
return (TEnum) (object)
Enum.GetValues(typeof(TEnum))
.Cast<int>()
.Aggregate(0, (s, f) => s | f);
}
这个双重演员的全部功劳归于@millimoose
答案 3 :(得分:1)
确保将所有枚举位设置为仅设置所有位的最简单方法:
mytest allValues = (mytest)int.MaxValue;
这假设设置与任何枚举不对应的位没有问题,但这可能是真的。你可以将它与任何枚举值进行对比,它会出现真实,这很可能是最终目标。
答案 4 :(得分:1)
像
这样的东西var all = Enum.GetValues(typeof(MyEnum)).Cast<MyEnum>().Last() * 2 - 1;
基本上
all = max*2-1
仅当所有值都从1到最大值时才有效。
... 1,2,4 ... 32,64
答案 5 :(得分:0)
鉴于潜在的类型演员问题,它并不像第一眼看上去那么容易:
static public TEnum GetAllFlags<TEnum>() where TEnum : struct, IComparable, IFormattable, IConvertible
{
unchecked
{
if (!typeof(TEnum).IsEnum)
throw new InvalidOperationException("Can't get flags from non Enum");
object val = null;
switch (Type.GetTypeCode(Enum.GetUnderlyingType(typeof(TEnum))))
{
case TypeCode.Byte:
case TypeCode.SByte:
val = Enum.GetValues(typeof(TEnum))
.Cast<Byte>()
.Aggregate(default(Byte), ( s, f) => (byte)(s | f));
break;
case TypeCode.Int16:
case TypeCode.UInt16:
val = Enum.GetValues(typeof(TEnum))
.Cast<UInt16>()
.Aggregate(default(UInt16), ( s, f) => (UInt16)(s | f));
break;
case TypeCode.Int32:
case TypeCode.UInt32:
val = Enum.GetValues(typeof(TEnum))
.Cast<UInt32>()
.Aggregate(default(UInt32), ( s, f) => (UInt32)(s | f));
break;
case TypeCode.Int64:
case TypeCode.UInt64:
val = Enum.GetValues(typeof(TEnum))
.Cast<UInt64>()
.Aggregate(default(UInt64), ( s, f) => (UInt64)(s | f));
break;
default :
throw new InvalidOperationException("unhandled enum underlying type");
}
return (TEnum)Enum.ToObject(typeof(TEnum), val);
}
}
有关此类转换的更多信息,请访问here