确定是否在某个值上设置了任何标志

时间:2014-08-31 18:07:21

标签: c#

假设我有以下内容:

[Flags]
public enum Options : long
{
    None = 0,

    Flag1 = 0x00000001,
    Flag2 = 0x00000002,
    Flag3 = 0x00000004,
    Flag4 = 0x00000008,
    Flag5 = 0x00000010,
    // ...
    FlagV = 0x10000000000,
    FlagW = 0x20000000000,
    FlagX = 0x40000000000,
    FlagY = 0x80000000000,
    FlagZ = 0x100000000000
}

目前,为了确定是否设置了标志,我这样做:

(myOptions & (long)Options.Flag1) == (long)Options.Flag1

如何确定FlagV上方的任何标志(例如FlagW,FlagX等)是否已设置并检索其值(例如,如果设置了FlagW,FlagX和FlagZ,我想检索FlagW的值)?换句话说,是否有替代方案:

if ((myOptions & (long)Options.FlagW) == (long)Options.FlagW)
    return (long)Options.FlagW;
else if ((myOptions & (long)Options.FlagX) == (long)Options.FlagX)
    return (long)Options.FlagX;
else if ((myOptions & (long)Options.FlagY) == (long)Options.FlagY)
    return (long)Options.FlagY;
// etc.

4 个答案:

答案 0 :(得分:3)

您可以遍历所有选项值。

var currentVal = Options.FlagV | Options.FlagW;
     foreach (Options enumVal in Enum.GetValues(typeof(Options)))
         if (enumVal > Options.FlagV && (enumVal & currentVal) == enumVal)
                //Do stuff

答案 1 :(得分:2)

这将为您提供myOptions中设置的标记列表:

var flags = Enum.GetValues(typeof(Options))
                .Where(f => myOptions.HasFlag(f))
                .ToList();

编辑:您的myOptions实际上很长,否则您的代码将无法编译,因为您无法将&应用于枚举和长整数。所以试试这个:

var enumVal = (Options)myOption;
var flags = Enum.GetValues(typeof(Options))
                .Where(f => enumVal.HasFlag(f))
                .ToList();

答案 2 :(得分:1)

首先,您可能需要重新考虑导致超过32个标志的设计,因为这听起来很麻烦。

除此之外,请考虑您只是进行位算术,因此以下内容既有效(编译成几条指令),又易于维护:

public enum Options : long
{
    FlagA = 0x00000001,
    // ...
    FlagZ = 0x80000000,
    // ...
    HighFlags = 0xffff0000,
    LowFlags  = 0x0000ffff
}

然后,您可以HighFlags检查任何(options & Options.HighFlags) != 0,并HighFlags只获取options & Options.HighFlags

如果您无法修改枚举,或者不想依赖特定值,您还可以在运行时or将这些值放在一起:

public static class OptionsHelper
{
    private readonly static Options HighFlags = Options.FlagM 
        | Options.FlagN
        // ...
        | Options.FlagZ;

    public static bool HasHighFlags(this Options opt)
    {
        return (opt & HighFlags) != 0;
    }

    public static Options GetHighFlags(this Options opt)
    {
        return (opt & HighFlags);
    }

    public static IEnumerable<Options> GetSetHighFlags(this Options opt)
    {
        var highFlags = GetHighFlags(opt);

        if (highFlags != 0)
        {
            for (ulong cFlag = 1; cFlag != 0; cFlag <<= 1)
            {
                if ((highFlags & cFlag) != 0)
                {
                    yield return (Options)cFlag;
                }
            }
        }
    }
}

用作扩展方法(options.HasHighFlags())或options.GetSetHighFlags().First()

答案 3 :(得分:0)

您可以简单地执行以下操作:

if (optons & 0xfe0000000000) // Typecasts will be needed
    // One of those flags is set.

另请注意,较新版本的.NET支持options.HasFlag()方法,这可以简化确定是否定义了标志。

事实上,我没有测试它,但你应该可以做这样的事情:

if (optons.HasFlag(0xfe0000000000)) // Typecasts will be needed
    // One of those flags is set.