if 语句 - “或”但不是“和”
本文关键字:语句 if | 更新日期: 2023-09-27 18:35:27
在 C Sharp 中,如何设置一个 if 语句来检查几个条件之一是否为真?它必须只是条件之一,如果零或两个或更多为真,则 if 应该是假的。
您可以编写一个帮助程序方法。这样做的好处是它可以短路,只根据需要精确地评估,
public static bool IsExactlyOneTrue(IEnumerable<Func<bool>> conditions) {
bool any = false;
foreach (var condition in conditions) {
bool result = condition();
if (any && result) {
return false;
}
any = any | result;
}
return any;
}
List<Func<Customer, bool>> criteria = new List<Func<Customer, bool>>();
criteria.Add(c => c.Name.StartsWith("B"));
criteria.Add(c => c.Job == Jobs.Plumber);
criteria.Add(c => c.IsExcellent);
Customer myCustomer = GetCustomer();
int criteriaCount = criteria
.Where(q => q(myCustomer))
// .Take(2) // optimization
.Count()
if (criteriaCount == 1)
{
}
Jason 方法签名的 Linq 实现:
public static bool IsExactlyOneTrue(IEnumerable<Func<bool>> conditions)
{
int passingConditions = conditions
.Where(x => x())
// .Take(2) //optimization
.Count();
return passingConditions == 1;
}
您可以使用将
布尔值组合成bool
序列,然后应用 LINQ:
bool[] conditions = new bool[] { cond1, cond2, cond3, cond4 };
bool singleTrue = conditions.Count(cond => cond) == 1;
对于两个布尔值,独占或变得简单得多:
bool singleTrue = cond1 != cond2;
编辑:为了实现按需评估和短路,我们需要将我们的bool
序列提升为Func<bool>
序列(其中每个元素都是封装条件评估的函数委托):
IEnumerable<Func<bool>> conditions = // define sequence here
int firstTrue = conditions.IndexOf(cond => cond());
bool singleTrue = firstTrue != -1 &&
conditions.Skip(firstTrue + 1).All(cond => !cond());
上面的代码片段假定存在基于谓词的IndexOf
运算符,该运算符在当前版本的 LINQ 下不可用,但可以定义为扩展方法,如下所示:
public static int IndexOf<T>(this IEnumerable<T> source, Func<T, bool> predicate)
{
int i = 0;
foreach (T element in source)
{
if (predicate(element))
return i;
i++;
}
return -1;
}
用于测试的示例数据(可以在评估后的每个false
或true
上设置断点):
IEnumerable<Func<bool>> conditions = new Func<bool>[]
{
() =>
false,
() =>
true,
() =>
false,
() =>
false,
};
为了简单起见,您可以保持运行计数:
int totalTrue = 0;
if (A) totalTrue++;
if (B) totalTrue++;
if (C) totalTrue++;
...
return (1 == totalTrue);
我认为这可以解决问题
int i= 0;
if ( (!A || ++i <= 1) &&
(!B || ++i <= 1) &&
(!C || ++i <= 1) &&
... &&
(i == 1))
如果我在这一点上没有想错,这个if
一i > 1
就会是假的.如果i
从不递增,我们到达最后一个条件,则自i == 0
以来将是假
这些答案中的大多数都有效并且具有"良好的表现"。但最简单的答案是:
if( (A & !(B || C)) ||
(B & !(A || C)) ||
(C & !(A || B)) )
{
...
}
您最终会不止一次地评估A/B/C,因此这仅在具有简单布尔值时才有用。