C# 重构嵌套的If

C# 重构嵌套的If,c#,algorithm,C#,Algorithm,假设您有5个返回布尔值的函数,根据函数返回的值,您需要返回一个值。比如说 函数f1、f2、f3、f4、f5都不带参数并返回true或false。这将为您提供2^5种可能性,对于每种可能性,您需要返回一个唯一的数字,以便 f1() = true, f2() = true, f3() = true, f4() = true, f5() = true return 1 f1() = true, f2() = true, f3() = true, f4() = true, f5() = false r

假设您有5个返回布尔值的函数,根据函数返回的值,您需要返回一个值。比如说

函数f1、f2、f3、f4、f5都不带参数并返回true或false。这将为您提供2^5种可能性,对于每种可能性,您需要返回一个唯一的数字,以便

f1() = true, f2() = true, f3() = true, f4() = true, f5() = true return 1

f1() = true, f2() = true, f3() = true, f4() = true, f5() = false return 2

f1() = true, f2() = true, f3() = true, f4() = false, f5() = false return 3
..
..
除了使用大量嵌套if,还有什么干净的方法可以做到这一点

其他详情:


这是我正在研究的一个问题的简化。根据上面的一些函数,我试图确定由枚举表示的订单的状态。例如,我正在做:IfCertainCondition1和IfCertainCondition2然后是OrderFormStatus.New,IfCertainCondition1和非IfCertainCondition2然后是OrderFormStatus.SomethingElse。这样做是可行的,但由于存在大量的条件,因此会产生非常重的嵌套if

,您可以将它们组合成一个整数,整数中的每一位表示一个方法返回的布尔值

unsigned int foo =   ( f1() ? 1 : 0 ) 
                   | ( ( f2() ? 1 : 0 ) << 1 )
                   | ( ( f3() ? 1 : 0 ) << 2 )
                   | ( ( f4() ? 1 : 0 ) << 3 )
                   | ( ( f5() ? 1 : 0 ) << 4 );

switch ( foo ) {
    case 0:
        // Whatever you do if they're all false
        break;
    case 1:
        // Blah blah blah
        break;
    // ... 23 more cases ... 
}
bool f1, f2, f3, f4, f5;
int combined = f1 ? 0x01 : 0 | f2 ? 0x02 : 0 | f3 ? 0x04 : 0 | f4 ? 0x08 : 0 | f5 ? 0x10 : 0;
return combined;
// or 
int conversionTable[32] = { ... };
return conversionTable[combined];
怎么样

int x = 0;
if (f1()) x+=16;
if (f2()) x+=8;
if (f3()) x+=4;
if (f4()) x+=2;
if (f5()) x+=1;
return x;
从结果中,您可以检查余数并确切知道哪些函数返回true

在.NET中,布尔类型保存值True 1或False 0。您可以利用该漏洞编写代码,而无需任何条件:

int x = (int)f1();
x |= ((int)f2()) << 1;
x |= ((int)f3()) << 2;
x |= ((int)f4()) << 3;
x |= ((int)f5()) << 4;
或者,如果不希望布尔值始终为0或1:

foreach (var f in funcs)
{
    x <<= 1;
    if (f())
        x |= 1;
}
然后可以使用上面的代码生成值,并将其强制转换为枚举类型。也就是说,在计算x之后,写出:

或者,如果值为1..32而不是0..31:

OrderFormStatus ofs = (OrderFormStatus)(x+1);

有了更多的细节,可能有人会帮你重新思考这个设计。我在现实生活中从未遇到过这样的情况,我同意。你应该试着重新思考你的逻辑,看看是否有更好的方法来实现你想要实现的目标do@pwny当前位置这样的事情并不少见,尽管我们经常用不同的方式来表达。设想一个程序使用五个或更多相互关联的条件来评估风险。你不能说条件1会使你的风险增加X,因为它的影响取决于条件2或条件3是否也是正确的。因此,您创建了一个映射表,该表根据所有条件的真/假值返回预先计算的风险值。有很多方法可以实现这样的事情,这就是其中之一。我理解你的前提,这很有意义。然而,在这种情况下,这感觉像是一个有争议的决定;如果这里的人能得到更多的细节,他们也许能够帮助改进这个决定。我的意思是说,我从未遇到过这样的情况:一堆嵌套的if语句是唯一的,甚至是最优雅的解决方案。虽然组合成整数的方法非常有趣,我一开始没有考虑到这一点,但我认为f5应该返回0x16 tho。0x10将设置0x02和0x08bits@Nicklamort:否,f5应返回0x10 16十进制。这是我第一次阅读问题时想到的答案。干得好。
public enum OrderFormStatus
{
    New = 1,
    SomethingElse = 2,
    // ... etc
}
OrderFormStatus ofs = (OrderFormStatus)x;
OrderFormStatus ofs = (OrderFormStatus)(x+1);