重构嵌套的If

时间:2011-03-04 17:07:26

标签: 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 return 2

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

除了使用大量的嵌套if之后,还有一种干净的方法吗?

其他详情:

这是我正在处理的问题的简化。基于一些像上面那样工作的函数,我试图确定一个由枚举表示的订单表单的状态。例如我正在做:IfCertainCondition1()和IfCertainCondition2()然后是OrderFormStatus.New,IfCertainCondition1()和NOT IfCertainCondiction2()然后是OrderFormStatus.SomethingElse。这样做有效但因为有很多条件会使非常重的嵌套if

4 个答案:

答案 0 :(得分:7)

您可以将它们组合成一个整数,整数中的每个位代表bool从一个方法返回。

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];

答案 1 :(得分:4)

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 ... 
}

答案 2 :(得分:1)

在.NET中,Boolean类型包含值True(1)或False(0)。您可以利用它并编写代码而不需要任何条件:

int x = (int)f1();
x |= ((int)f2()) << 1;
x |= ((int)f3()) << 2;
x |= ((int)f4()) << 3;
x |= ((int)f5()) << 4;

您可以构造上面的代码,以便它返回您想要的值,而无需求助于将计算出的x值映射到您想要返回的实际值的查找表。

另一种方法是创建一个函数数组:

Func<bool>[] funcs = new Func<bool>[] { f1, f2, f3, f4, f5 };
int x = 0;
foreach (var f in funcs)
{
    x = (x << 1) | (int)f();
}

或者,如果您不想依赖Boolean始终为0或1:

foreach (var f in funcs)
{
    x <<= 1;
    if (f())
        x |= 1;
}

稍后添加,在您提供其他详细信息后:

你说你正在使用枚举。我假设您的值为0到31(或者可能是1到32),例如:

public enum OrderFormStatus
{
    New = 1,
    SomethingElse = 2,
    // ... etc
}

然后,您可以使用上面的代码生成您的值,然后将其强制转换为枚举类型。也就是说,在计算x之后,写下:

OrderFormStatus ofs = (OrderFormStatus)x;

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

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

答案 3 :(得分:0)

怎么样

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;

相关问题