Рефакторинг вложенных If - PullRequest
0 голосов
/ 04 марта 2011

Скажем, у вас есть 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 ]

7 голосов
/ 04 марта 2011

Вы можете объединить их в одно целое число, причем каждый бит в целом числе представляет возврат 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];
4 голосов
/ 04 марта 2011
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 ... 
}
1 голос
/ 04 марта 2011

В .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;

Вы можете потенциально структурировать приведенный выше код так, чтобы он возвращал нужные значения без обращения к таблице поиска, которая отображает вычисленные значения * 1007.* значение к фактическому значению, которое вы хотите вернуть.

Другой способ сделать это - создать массив функций:

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

Добавлен позже, после того, как вы добавите дополнительные данные:

Вы говорите, что используете enum.Я предполагаю, что у вас есть значения от 0 до 31 (или, возможно, от 1 до 32), что-то вроде:

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

Затем вы можете использовать приведенный выше код для генерации вашего значения и просто привести его к типу enum.То есть после вычисления x напишите:

OrderFormStatus ofs = (OrderFormStatus)x;

Или, если ваши значения 1..32, а не 0..31:

OrderFormStatus ofs = (OrderFormStatus)(x+1);
0 голосов
/ 04 марта 2011

Как насчет

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;

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...