位掩码枚举的通用单标志枚举 [英] Generic single flag enumeration for bitmask enums

查看:135
本文介绍了位掩码枚举的通用单标志枚举的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用带有几个位标记枚举的代码库工作,这些枚举看起来像这样

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆