假设我有以下内容:
[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.
答案 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.