用很多ifs简化代码

时间:2011-01-02 17:19:02

标签: c# optimization simplify

我有一个基于枚举的方法,并且在开始时我们有这种情况:

public void MyMetohd(Somestatus status)
{
if(status == Somestatus.Enum1)
{
DoA();
DoB();
DoC();
DoD();
DoE();
}
if(status == Somestatus.Enum2)
{
DoA();
DoB();
DoC();
DoD();
}

if(status == Somestatus.Enum3)
{
DoA();
DoB();
DoC();
}

if(status == Somestatus.Enum4)
{
DoA();
DoB();
}

if(status == Somestatus.Enum5)
{
DoA();
}
}

你会如何优化这种代码(它不是我的代码)?

10 个答案:

答案 0 :(得分:5)

如果您设置enum的每个成员的值,则可以使用比较。

enum Somestatus : int
{
    Enum1 = 1,
    Enum2 = 2,
    ...
}

然后只需使用比较来完成代码。因为你总是DoA(),所以从那开始。

if(status <= Somestatus.Enum5)
    DoA();

if(status <= Somestatus.Enum4)
    DoB();

if(status <= Somestatus.Enum4)
    DoC();
...

继续这样做。这样,当值为Enum1时,将调用所有函数。

答案 1 :(得分:5)

通过优化我会假设你的意思是“制造DRYer”。

你将不得不在易于阅读的代码(你拥有的代码,虽然略有重复性)和尽可能少重复的代码之间取得平衡

只要输入这个就会让我觉得很脏,但如果你想要的是DRY和更少的LOC,我认为它会做你想要的。

switch (status)
            {
                case Somestatus.Enum1:
                    DoE();
                    goto SomeStatus.Enum2;
                case Somestatus.Enum2:
                    DoD();
                    goto SomeStatus.Enum3;
                case Somestatus.Enum3:
                    DoC();
                    goto SomeStatus.Enum4;
                case Somestatus.Enum4:
                    DoB();
                    goto SomeStatus.Enum5;
                case Somestatus.Enum5:
                    DoA();
                    break;
                default:
                    throw new InvalidArgumentException("Unknown Status");
            }

答案 2 :(得分:3)

您可以在枚举值上使用字典键,并使用ActionAction<T>列表来执行。

Dictionary<int,IList<Action>> actionsPerEnumValue;

使用枚举值和每个字符的操作填充此字典。

在你的函数中获取每个值的函数列表并调用每个动作。

foreach(var act in actionsPerEnumValue[status])
{
    act();
}

请参阅this SO答案以获取示例。

答案 3 :(得分:0)

乍一看,switch语句似乎是最好的方法,但即使在那个方面你也有很多重复的代码:

switch (status)
{
    case Somestatus.Enum1:
        DoA();
        DoB();
        DoC();
        DoD();
        DoE();
        break;
    case Somestatus.Enum2:
        DoA();
        DoB();
        DoC();
        DoD();
        break;
    ...
}

虽然这样做会更好,但仍然不理想,因为您重复调用了DoA等。

答案 4 :(得分:0)

当你在相同的条件和不同的价值上工作时,当时更好的你使用switch..case ... 如果要测试多个条件,请使用If..else。

答案 5 :(得分:0)

你也可以“反转”逻辑,如果它更简单(取决于要覆盖的枚举数量与不同行动的数量):

if(status == Somestatus.Enum1 || status == Somestatus.Enum2)
 DoA();

if(status == Somestatus.Enum1 || status == Somestatus.Enum4)
 DoB();

...

答案 6 :(得分:0)

听起来应该使用State Pattern

答案 7 :(得分:0)

<强>编辑:

// ANOTHER WAY
public void MyMetohd(Somestatus status)
{
    switch(status)
    {
        case Somestatus.Enum1:
             do_("ABCDE");
             break;
        case Somestatus.Enum2:
             do_("ABCD");
             // and so on...
        }
}

public static void do_(string s)
{
    foreach(char ch in s)
    {
        switch(ch)
        {
            case 'A':
                 doA();
                 break;
            case 'B':
                 doB();
                 break;
            case 'C':
                 doC();
                 break;
            case 'D':
                 doD();
                 break;
            case 'E':
                 doE();
                 break               
        }
    }
}

答案 8 :(得分:0)

使用模式来解决这个问题将是其他人建议的最佳解决方案。我想提供另一种解决方案。

我强烈建议不要这样做。

public void MyMetohd(Somestatus status)
    DoA();
    if (status != SomeStatus.Enum5) {
        DoB();
        if (status != SomeStatus.Enum4) {
            DoC();
            if (status != SomeStatus.Enum3) {
                DoD();
                if (status != SomeStatus.Enum2) {
                    DoE();
                }
            }
        }
    }
}

答案 9 :(得分:0)

虽然我自己会选择Brook的解决方案,但我想指出另一个优雅而简短的解决方案。

public void MyMethod(Somestatus status)
{
    foreach (Action toDo in new Action[] { DoA, DoB, DoC, DoD, DoE }.Take(5 - (int)status))
        toDo();
}

但是,这假定Somestatus的定义如下:

enum Somestatus
{
    Enum1,
    Enum2,
    Enum3,
    Enum4,
    Enum5
}

我喜欢这个解决方案作为一个学者,因为它很短,但它肯定没有很好的可读性或可维护性。