在标志上使用按位运算符

时间:2009-02-09 21:33:59

标签: c# .net bit-manipulation bit-fields

我有四个标志

Current = 0x1  
Past = 0x2  
Future = 0x4  
All = 0x7

说我收到过去和未来两个标志(setFlags(PAST | FUTURE))。如何判断Past是否在其中?同样,我如何判断Current不在其中?这样我就不必测试每种可能的组合。

9 个答案:

答案 0 :(得分:43)

如果您希望测试掩码中的所有位匹配:

if((value & mask) == mask) {...}

如果您希望测试掩码中的任何一位匹配:

if((value & mask) != 0) {...}

当您测试多个事物的值时,差异最明显。

测试排除:

if ((value & mask) == 0) { }

答案 1 :(得分:29)

首先 - 使用带有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;

答案 2 :(得分:12)

您可能还想添加扩展方法,例如

  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
 }

答案 3 :(得分:4)

if ((flags & PAST) == PAST)
{
  // PAST is there
}

if ((flags & CURRENT) != CURRENT)
{
  // CURRENT is not there
}

答案 4 :(得分:3)

如果您使用.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...
}

答案 5 :(得分:1)

Marc Gravell和Vilx的补遗 - 答案:

您标记的枚举不应指定"所有"的金额,它应该只包括您现有的值。这适用于任何计算值。

[Flags]
public enum Time
{
    None = 0,
    Current = 1,
    Past = 2,
    Future = 4,
    All = Current | Past | Future
}

请注意,Vilx-删除了使用十六进制值。这很重要,因为一旦超过0x8,您的值必须符合Hex。你应该保持小数。

修改 我还想补充一点,你可以使用位移而不是十六进制/十进制。

这看起来像:

[Flags]
public enum Time
{
    None = 0,
    Current = 1,
    Past = 1 << 1, // 2, 10 binary
    Future = 1 << 2, // 4, 100 binary
    All = Current | Past | Future
}

答案 6 :(得分:0)

(value & Current) == Current

答案 7 :(得分:0)

我认为所缺少的是只吃一个而已。

[Flags]
public enum Time
{
    None = 0,
    Current = 1,
    Past = 1 << 1, // 2, 10 binary
    Future = 1 << 2, // 4, 100 binary
    All = Current | Past | Future
}

然后使用上面的标志枚举,就可以

var notNow= Time&~Time.Current;

答案 8 :(得分:-1)

您可以使用AND并检查结果是否与您相同并使用?