【发布时间】:2010-08-11 21:37:12
【问题描述】:
我有一个带有标志属性的枚举。
我的问题是,我想获得所有选项的整数位掩码,而无需自己手动组合所有位。 我想这样做以与其他一些 int 字段进行比较,并且我想保护以防未来的开发人员向枚举广告更多位选项。
另一件事是我的枚举标志中的位将全部手动分配,所以我不能简单地获取下一个值并减去 1。
【问题讨论】:
我有一个带有标志属性的枚举。
我的问题是,我想获得所有选项的整数位掩码,而无需自己手动组合所有位。 我想这样做以与其他一些 int 字段进行比较,并且我想保护以防未来的开发人员向枚举广告更多位选项。
另一件事是我的枚举标志中的位将全部手动分配,所以我不能简单地获取下一个值并减去 1。
【问题讨论】:
如果我理解你的要求正确,这应该对你有用:
Enum.GetValues(typeof(Enum)).Cast<int>().Sum();
然后您可以将其转换回您的typeof(Enum):
[Flags]
public enum Values
{
Value_1 = 1,
Value_2 = 2,
Value_3 = 4,
Value_4 = 8,
Value_5 = 16,
Value_6 = 32,
Value_7 = 64,
Value_8 = 128,
Value_9 = 256
}
static void Main(string[] args)
{
Values values = (Values)Enum.GetValues(typeof(Values)).Cast<int>().Sum();
}
【讨论】:
// uses a ulong to handle all possible underlying types without error
var allFlags = Enum.GetValues(typeof(YourEnumType))
.Cast<YourEnumType>()
.Aggregate((YourEnumType)0, (a, x) => a | x, a => (ulong)a);
【讨论】:
ulong,以便它可以处理所有可能的基础类型。 (我将其转换为 YourEnumType 而不是保留它,因为 OP 要求提供 integer 位掩码。)
看看我的 Unconstrained Melody 项目,它做了一些坏事,允许在受限于枚举和委托的泛型方法上构建好的功能。
在这种情况下,我想你应该打电话给Flags.GetUsedBits<YourEnumType>()。
如果您不介意使用额外的(非常小的)库,我想 Unconstrained Melody 在处理标志时让生活更美好。如果您有任何功能要求,我很乐意看看 :)
【讨论】:
有点粗鲁但像这样?
[Flags]
enum SomeFlags
{
Flag1 = 1,
Flag2 = 2,
Flag3 = 4,
Flag4 = 16,
Flag5 = 32,
Flag6 = 64
}
static void Main(string[] args)
{
SomeFlags flags = 0;
SomeFlags[] values = (SomeFlags[])Enum.GetValues(typeof(SomeFlags));
Array.ForEach<SomeFlags>(values, delegate(SomeFlags v) { flags |= v; });
int bitMask = Convert.ToInt32(flags);
}
【讨论】:
这是一种方法,使用 Jon Skeet 和 Marc Gravell 编写的 generic operators 中的想法:
void Main()
{
Console.WriteLine(CombineAllFlags<MyEnum>()); // Prints "Foo, Bar, Baz"
}
[Flags]
public enum MyEnum
{
Foo = 1,
Bar = 2,
Baz = 4
}
public static TEnum CombineAllFlags<TEnum>()
{
TEnum[] values = (TEnum[])Enum.GetValues(typeof(TEnum));
TEnum tmp = default(TEnum);
foreach (TEnum v in values)
{
tmp = EnumHelper<TEnum>.Or(tmp, v);
}
return tmp;
}
static class EnumHelper<T>
{
private static Func<T, T, T> _orOperator = MakeOrOperator();
private static Func<T, T, T> MakeOrOperator()
{
Type underlyingType = Enum.GetUnderlyingType(typeof(T));
ParameterExpression xParam = Expression.Parameter(typeof(T), "x");
ParameterExpression yParam = Expression.Parameter(typeof(T), "y");
var expr =
Expression.Lambda<Func<T, T, T>>(
Expression.Convert(
Expression.Or(
Expression.Convert(xParam, underlyingType),
Expression.Convert(yParam, underlyingType)),
typeof(T)),
xParam,
yParam);
return expr.Compile();
}
public static T Or(T x, T y)
{
return _orOperator(x, y);
}
}
此代码动态创建一个将枚举值与 OR 运算符组合的委托
【讨论】: