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

C# 确定是否在某个值上设置了任何标志,c#,C#,假设我有以下几点: [Flags] public enum Options : long { None = 0, Flag1 = 0x00000001, Flag2 = 0x00000002, Flag3 = 0x00000004, Flag4 = 0x00000008, Flag5 = 0x00000010, // ... FlagV = 0x10000000000, FlagW = 0x20000000000,

假设我有以下几点:

[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.

您可以遍历所有选项值

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

您可以遍历所有选项值

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

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

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

编辑:看起来您的
myOptions
实际上是一个long,否则您的代码将无法编译,因为您无法将
&
应用于枚举和long。因此,请尝试以下方法:

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

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

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

编辑:看起来您的
myOptions
实际上是一个long,否则您的代码将无法编译,因为您无法将
&
应用于枚举和long。因此,请尝试以下方法:

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

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

除此之外,考虑到您只在执行位运算,所以如下所示的一些方法都是高效的(编译成一对夫妇指令),并且易于维护:

public enum Options : long
{
    FlagA = 0x00000001,
    // ...
    FlagZ = 0x80000000,
    // ...
    HighFlags = 0xffff0000,
    LowFlags  = 0x0000ffff
}
然后,您可以通过执行
(options&options.HighFlags)!=0
并使用
选项和选项仅获取
高标志
。高标志

如果无法修改枚举,或不想依赖特定值,也可以在运行时将这些值组合在一起:

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;
                }
            }
        }
    }
}
公共静态类选项帮助器
{
私有只读静态选项HighFlags=Options.FlagM
|选项.FlagN
// ...
|Options.FlagZ;
公共静态bool HasHighFlags(此选项可选)
{
返回(可选和高标志)!=0;
}
公共静态选项GetHighFlags(此选项可选)
{
返回(选择和高标记);
}
公共静态IEnumerable GetSetHighFlags(此选项可选)
{
var highFlags=GetHighFlags(opt);
如果(高标志!=0)
{

对于(ulong cFlag=1;cFlag!=0;cFlag首先,您可能需要重新考虑导致您使用超过32个标志的设计,因为这本身听起来很麻烦

除此之外,考虑到您只在执行位运算,所以如下所示的一些方法都是高效的(编译成一对夫妇指令),并且易于维护:

public enum Options : long
{
    FlagA = 0x00000001,
    // ...
    FlagZ = 0x80000000,
    // ...
    HighFlags = 0xffff0000,
    LowFlags  = 0x0000ffff
}
然后,您可以通过执行
(options&options.HighFlags)!=0来检查任何
HighFlags
,并使用
options&options.HighFlags
仅获取
HighFlags

如果无法修改枚举,或不想依赖特定值,也可以在运行时将这些值组合在一起:

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;
                }
            }
        }
    }
}
公共静态类选项帮助器
{
私有只读静态选项HighFlags=Options.FlagM
|选项.FlagN
// ...
|Options.FlagZ;
公共静态bool HasHighFlags(此选项可选)
{
返回(可选和高标志)!=0;
}
公共静态选项GetHighFlags(此选项可选)
{
返回(选择和高标记);
}
公共静态IEnumerable GetSetHighFlags(此选项可选)
{
var highFlags=GetHighFlags(opt);
如果(高标志!=0)
{

对于(ulong cFlag=1;cFlag!=0;cFlag您可以简单地执行以下操作:

if (optons & 0xfe0000000000) // Typecasts will be needed
    // One of those flags is set.
if (optons.HasFlag(0xfe0000000000)) // Typecasts will be needed
    // One of those flags is set.
另外,请注意,较新版本的.NET支持
options.HasFlag()
方法,这简化了确定是否定义了标志的过程

事实上,我没有测试它,但您应该能够执行以下操作:

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

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

if (optons & 0xfe0000000000) // Typecasts will be needed
    // One of those flags is set.
if (optons.HasFlag(0xfe0000000000)) // Typecasts will be needed
    // One of those flags is set.
另外,请注意,较新版本的.NET支持
options.HasFlag()
方法,这简化了确定是否定义了标志的过程

事实上,我没有测试它,但您应该能够执行以下操作:

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

要检查是否设置了任何标志,请使用
myOptions!=0
。要检索其值,只需按位AND(
&
)它使用了标志本身。对不起。为了更清楚起见,编辑了我的问题。基本上,我正在尝试确定是否设置了FlagV上方的任何标志,如果设置了,该标志是什么。@arao6您的最后一个代码片段与
return myOptions;
等效。基本上,在清除所有不关心的标志后,您只需要寻找LEATt设置的有效位,其中一些应该很容易适应C#。顺便说一句,你似乎要问的问题的答案(但不是你实际想要的,基于你问题的其余部分)更简单:确定是否有任何标志设置为
W
X
Y
只是
myOptions&(Options.W | Options.X | Options.Y)!=0
(根据
myOptions
的类型进行必要的强制转换)。要检查是否设置了任何标志,请使用
myOptions!=0
。检索其值,只需按位和(
&
)它使用了标志本身。对不起。为了更清楚起见,编辑了我的问题。基本上,我正在尝试确定是否设置了FlagV上方的任何标志,如果设置了,该标志是什么。@arao6您的最后一个代码片段与
return myOptions;
等效。基本上,在清除所有不关心的标志后,您只需要寻找LEATt设置的有效位,其中一些应该很容易适应C#。顺便说一句,你似乎要问的问题的答案(但不是你实际想要的,基于你问题的其余部分)更简单:确定是否有任何标志设置为
W
X
Y
只是
myOptions&(Options.W | Options.X | Options.Y)!=0
(根据
myOptions
的类型进行必要的强制转换)。我希望可以接受多个答案:)您的方法