[英]Check bitwise flags that cannot co-exist with each other
我有旗幟
int A = 1;
int B = 2;
int C = 4;
我想檢查一下,一個函數只能指定一個標志
check(A | B | C) ; // invalid
check(A); // valid
check(B); // valid
check(B | C); // invalid
void check(int flags) {
// check that if A is specified, then B and C can't
// check that if B is specified, then A and C can't
// check that if C is specified, then B and A can't
}
沒有大量的“ if”語句,如何實現?
要將位設置在位置n ,您需要設置值2 ^ n 。
因此,如果您要檢查是否僅指定了一個標志,那么您只想詢問數字是否為2的冪。
這是一個有關如何執行此操作的問題: 如何檢查數字是否為2的冪
就像GrahamS所說的那樣,您可能會讀到這樣的問題,即必須設置一位(即不能為零)。 因此,此外,請檢查它是否為非零值並且小於或等於C。
也許不是最優雅的解決方案,但我認為它應該起作用:
bool check(int flags) {
int A = 1;
int B = 2;
int C = 4;
return
flags == 0 ||
flags == A ||
flags == B ||
flags == C;
}
為什么不對標志使用Enum,並檢查int值是否在枚舉中定義。
enum Flags
{
A = 1,
B = 2,
C = 4
}
void Check(int flags)
{
bool isValid = Enum.IsDefined(typeof(Flags), flags);
...
}
這是帶有switch的實現:
void check(int flags) {
swicth (flags & (A | B | C)) {
case A:
case B:
case C:
case 0:
return true;
default:
return false;
}
}
僅當A
, B
和C
是文字(即用const
標記)時,它才有效(在C#中)。 否則,您可以執行以下操作:
void check(int flags) {
int relevantPart = flags & (A | B | C);
return relevantPart == A || relevantPart == B || relevantPart == C || relevantPart == 0;
}
否則,請使用二乘冪技巧(摘自Joe的回答):
void check(int flags) {
int relevantPart = flags & (A | B | C);
return (relevantPart & (relevantPart - 1)) == 0;
}
我認為可能有比三個最低位更大的有效位,因此將其忽略。 我還假設A
, B
或C
都不有效(在我的解釋中這不是共存的)。
我要發表評論,但格雷厄姆斯所說的話很重要,足以說明這一點。
當您特別希望能夠設置倍數時,通常使用標志。 這是我們的任務枚舉的示例
namespace Shared.Enumerations
{
[Flags]
public enum TaskStatusEnum
{
NotSet = 0,
Open = 1,
Canceled = 2,
Complete = 4,
OnHold = 8,
Inactive = 32,
All = Open | Canceled | Complete | OnHold | Inactive
}
}
我們這樣做是為了可以說給我們任何打開或暫停的任務。
TaskList activeTasks = taskListManager.TaskList.FindAll(target.Name, target.TaskType, (TaskStatusEnum.Open | TaskStatusEnum.OnHold));
當然,使用常規枚舉一次只能設置一件事。 您實際上可以執行以下操作。
[TestMethod]
public void checkEnumVals()
{
var ts = TaskStatusTestEnum.Open;
ts |= TaskStatusTestEnum.OnHold;
bool matchBoth = false;
if ((ts & TaskStatusTestEnum.OnHold) == TaskStatusTestEnum.OnHold && (ts & TaskStatusTestEnum.Open) == TaskStatusTestEnum.Open)
matchBoth = true;
Assert.IsTrue(matchBoth);
}
我不會建議這樣的事情。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.