【发布时间】:2010-10-06 12:23:21
【问题描述】:
我有四个标志
Current = 0x1
Past = 0x2
Future = 0x4
All = 0x7
假设我收到了过去和未来的两个标志 (setFlags(PAST | FUTURE))。如何判断Past 是否在其中?同样,我怎么知道Current 不在其中?这样我就不必测试所有可能的组合。
【问题讨论】:
标签: c# .net bit-manipulation bit-fields
我有四个标志
Current = 0x1
Past = 0x2
Future = 0x4
All = 0x7
假设我收到了过去和未来的两个标志 (setFlags(PAST | FUTURE))。如何判断Past 是否在其中?同样,我怎么知道Current 不在其中?这样我就不必测试所有可能的组合。
【问题讨论】:
标签: c# .net bit-manipulation bit-fields
如果您希望测试掩码中的所有位都匹配:
if((value & mask) == mask) {...}
如果您希望测试掩码中的任何单个位匹配:
if((value & mask) != 0) {...}
当您测试多个事物的值时,差异最为明显。
测试排除:
if ((value & mask) == 0) { }
【讨论】:
首先 - 使用带有 FlagAttribute 的枚举。这就是它的用途。
[Flags]
public enum Time
{
None = 0
Current = 1,
Past = 2,
Future = 4
All = 7
}
然后测试是这样完成的:
if ( (x & Time.Past) != 0 )
或者这个:
if ( (x & Time.Past) == Time.Past )
如果“过去”是标志的组合并且您想全部测试它们,则后者会更好。
设置是这样的:
x |= Time.Past;
取消设置是这样的:
x &= ~Time.Past;
【讨论】:
PastOrPresent=3,因为1 & 2 = 3。只有为经常一起使用的组合添加这些才有意义。它可以节省打字并避免错误。
1 | 2 = 3。 :)
您可能还想添加这样的扩展方法
enum states {
Current = 0x1,
Past = 0x2,
Future = 0x4,
All = 0x7
};
static bool Is(this states current, states value) {
return (current & value) == value;
}
那么你可以这样做:
if(state.Is(states.Past)) {
// Past
}
【讨论】:
如果您使用 .NET 4 或更高版本,我更喜欢这样做,更干净的 imao:
[Flags]
public enum Time
{
None = 0
Current = 1,
Past = 2,
Future = 4
}
myProp = Time.Past | Time.Future;
if (myProp.HasFlag(Time.Past))
{
// Past is set...
}
【讨论】:
Marc Gravell 和 Vilx- 的答案的附录:
您的标记枚举不应指定“全部”的数量,它应该只包含您现有的值。这适用于任何计算值。
[Flags]
public enum Time
{
None = 0,
Current = 1,
Past = 2,
Future = 4,
All = Current | Past | Future
}
请注意,Vilx- 删除了十六进制值的使用。这很重要,因为一旦您超过 0x8,您的值将必须符合十六进制。你应该只保留十进制。
编辑: 我还想补充一点,您可以使用位移而不是十六进制/十进制。
这看起来像:
[Flags]
public enum Time
{
None = 0,
Current = 1,
Past = 1 << 1, // 2, 10 binary
Future = 1 << 2, // 4, 100 binary
// Example = 1 << 3, // 8, 1000 binary
// Example = 1 << 4, // 16, 10000 binary
All = Current | Past | Future
}
【讨论】:
Past = 1 << Current, Future = 1 << Past之类的东西代替硬编码的十进制值吗?
Current = 1 << 0 或 Current = 1 << None,正如你所说,Past = 1 << Current、Future = 1 << Past 将像我上面所说的那样工作。
if ((flags & PAST) == PAST)
{
// PAST is there
}
if ((flags & CURRENT) != CURRENT)
{
// CURRENT is not there
}
【讨论】:
(value & Current) == Current
【讨论】:
我认为缺少的是除一个以外的“全部”
[Flags]
public enum Time
{
None = 0,
Current = 1,
Past = 1 << 1, // 2, 10 binary
Future = 1 << 2, // 4, 100 binary
All = Current | Past | Future
}
然后用上面的flags枚举,就可以了
var notNow= Time&~Time.Current;
【讨论】: