如何在C#标志枚举中清除更高的字节

时间:2017-04-21 22:56:32

标签: c# bit-manipulation enum-flags

我正在使用Flags Enum来跟踪每个数据记录的数据迁移过程的完成阶段。我需要一种方法来重置回指定的阶段,我可以开始重新处理数据记录的迁移。如何重置Flags Enum中的较高字节?

示例枚举:

[Flags]
public Enum MigrationStages {
  None = 0,
  Started = 1,
  MiddleStage = 2,
  WrappingUp = 4,
  Finished = 8
}

我目前的价值:

var currentStage = 
    MigrationStages.None 
    | MigrationStages.Started 
    | MigrationStages.MiddleStage
    | MigrationStages.WrappingUp
    | MigrationStages.Finished;

我想重置回MigrationStages.MiddleStage,以便从那里开始重新处理。

1 个答案:

答案 0 :(得分:3)

按位数学不再是我们使用的东西了。因此,当我去寻找答案时,我发现没有任何帮助,所以我解决了。与世界分享我的数学,以防其他人发现它有用。

我创建了一个简单的帮助方法,如下所示:

public static MigrationStage ClearHigherFlags(MigrationStage orig, MigrationStage highBit)
{
    var lowerBits = (int)orig % (int)highBit;
    return highBit + lowerBits;
}

用法示例:

currentStage = ClearHigherFlags(currentStage, MigrationStages.MiddleStage);

显然,如果要清除包括highBit在内的更高标志,请不要将其添加回来。要清除较低的标记,return orig - lowerBits

在按位数学中,模数(%)通常是你的朋友。

附录

有些人会找到这个答案,并认为这不是真正的数学。我希望这能缓和那些人。

首先,回想一下,这是我们正在讨论的标志,因此是一个非常特定的位操作子集,其中模数使数学更容易阅读,非常合适。由编译器替换执行的实际数学将类似于下面的内容,我发现它更不直观。

public static MigrationStage ClearHigherFlags(MigrationStage orig, MigrationStage highBit)
{
    var bitMask = highBit - 1;
    var lowerBits = orig & bitMask;
    return highBit + lowerBits;
}

这真的不太难读,但转换为位掩码是在原始解决方案中隐式完成的。