位掩码枚举的通用单标志枚举 [英] Generic single flag enumeration for bitmask enums
问题描述
我正在使用带有几个位标记枚举的代码库工作,这些枚举看起来像这样
I'm working on a codebase with several bit flags enums which look something like this
public enum BitMask
{
None = 0,
OptionA = 1 << 0,
OptionB = 1 << 1,
OptionAandB = OptionA | OptionB,
All = ~0
}
我可以使用此
public IEnumerable<T> EnumValues<T>()
{
return Enum.GetValues(typeof(T)).Cast<T>();
}
我正在寻找一种通用方法,仅对单个标志值进行迭代,在这种情况下,是 OptionA
和 OptionB
。 不 无
, OptionAandB
,全部
。我可以强制转换为 long
并检测单个标志,因为它们是2的幂,因此在此处进行快速搜索可以发现这
I'm looking for a generic way to iterate over single flag values only, in this case, OptionA
and OptionB
. Not None
, OptionAandB
, All
. I can cast to long
and detect single flags as they are a power of two, a quick search on here suggests this
public bool IsPowerOfTwo(long val)
{
return (val != 0) && ((val & (val-1)) == 0) ;
}
Nongeneric版本工作正常
Nongeneric version works fine
public IEnumerable<BitMask> SingleFlagBitMaskValues()
{
return Enum.GetValues(typeof(BitMask))
.Cast<BitMask>()
.Where(e => IsPowerOfTwo((long)e));
}
但是通用版本无法编译,因为它不喜欢强制转换到 long
But the generic version doesn't compile because it doesn't like the cast to long
public IEnumerable<TEnum> SingleFlagEnumValues<TEnum>()
{
return Enum.GetValues(typeof(TEnum))
.Cast<TEnum>()
.Where(e => IsPowerOfTwo((long)e));
}
可以解决这个问题吗?
推荐答案
您可以使用 Convert.ToInt64 由于其许多重载:
You can use Convert.ToInt64 due to its many overloads:
public IEnumerable<TEnum> SingleFlagEnumValues<TEnum>()
{
return Enum.GetValues(typeof(TEnum))
.Cast<TEnum>()
.Where(e => IsPowerOfTwo(Convert.ToInt64(e)));
}
如评论中所建议,此处为优化:
As suggested in comments, here's for optimisation:
static class SingleFlagCache<TEnum>
{
internal static TEnum[] values = Enum.GetValues(typeof(TEnum))
.Cast<TEnum>()
.Where(e => IsPowerOfTwo(Convert.ToInt64(e))).ToArray();
}
public static IEnumerable<TEnum> SingleFlagEnumValues<TEnum>()
=> SingleFlagCache<TEnum>.values;
这篇关于位掩码枚举的通用单标志枚举的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!