有没有办法简化这个双条件子句结构?

时间:2012-03-28 09:55:11

标签: c#

例如

if (x=="A)
    switch (y)
    {
    case "1": Do1();break;
    case "2": Do2();break;
    case "3": Do3();break;
    }
else if (x=="B")
    switch (y)
    {
    case "1": Do4();break;
    case "2": Do5();break;
    case "3": Do6();break;
    }
else
    switch (y)
    {
    case "1": Do7();break;
    case "2": Do8();break;
    case "3": Do9();break;
    }

我希望我可以执行以下操作,但它有许多冗余检查。

    if (x=="A" && y=="1")
        Do1();
    else if (x=="A" && y=="2")
        Do2();
    else if (x=="A" && y=="3")
        Do3();
    else if (x=="B" && y=="1")
        Do4();
    else if (x=="B" && y=="2")
        Do5();
    else if (x=="B" && y=="3")
        Do6();
    else if (x=="C" && y=="1")
        Do7();
    else if (x=="C" && y=="2")
        Do8();
    else if (x=="C" && y=="3")
        Do9();

7 个答案:

答案 0 :(得分:2)

介绍OOPS的建议真的很棒,请不要忽视该评论。你可以暂时编写这样的代码。

var combinedText = x+y;
    switch(combinedText)
    {
        case "A1": Do1(); break;
        case "A2": Do2(); break;
        case "A3": Do3(); break;
        case "B1": Do4(); break;
        case "B2": Do5(); break;
        case "B3": Do6(); break;
        case "C1": Do7(); break;
        case "C2": Do8(); break;
        case "C3": Do9(); break;
    }

答案 1 :(得分:1)

void Main()
{
    Dictionary<string, Action> d = new Dictionary<string, Action>()
    {
        {"A1", Do1},
        {"A2", Do2},
        {"A3", Do3},
        {"B1", Do4},
        {"B2", Do5},
        {"B3", Do6},
        {"1", Do7},
        {"2", Do8},
        {"3", Do9}
    };
    var x = "A";
    var y = "1";
    var action = x == "A" || x == "B" ? x + y : y;
    if (d.ContainsKey(action))
        d[action]();
}

public void Do1() {}
public void Do2() {}
public void Do3() {}
public void Do4() {}
public void Do5() {}
public void Do6() {}
public void Do7() {}
public void Do8() {}
public void Do9() {}

修改

我记得这个fluent functional switch:

var sw = new Switch<string>(action)
                    .Case("A1", s => Do1())
                    .Case("A2", s => Do2());

答案 2 :(得分:1)

您的代码目前有两个职责 - 决定执行哪些方法(变量x)并决定执行哪个确切方法(变量y)。使代码更加清晰的最简单选项 - 拆分此职责并提取方法,这将决定调用方法集中的哪种方法

switch (x)
{
    case "A": DoA(y); break;
    case "B": DoB(y); break;
    default:
        DoDefault(y); break;
}

现在您的来电者代码很简单。这是DoX方法之一:

private void DoA(string y)
{
    switch (y)
    {
        case "1": Do1(); break;
        case "2": Do2(); break;
        case "3": Do3(); break;
    }
}

其他选项是使用.net来决定使用多态来调用哪组方法。但是在只有一个开关(x)块的简单情况下,我不建议这样做。如果您的实际代码更复杂,那么考虑提取将保存一组功能(Do1,Do2,Do3)的类,并决定该功能的执行。例如。调用代码:

IDo ido = CreateIDo(x);
ido.Do(y);

是的,就是这样。非常干净。这是IDo界面创建代码:

public static IDo CreateIDo(string x)
{
    switch (x)
    {
        case "A": return new A();
        case "B": return new B();
        default:
            return new C();
    }
}

这里是A类,它在执行它们时封装了第一组方法和决策:

public interface IDo
{
    void Do(string y);
}

public class A : IDo
{
    public void Do(string y)
    {
        switch (y)
        {
            case "1": Do1(); break;
            case "2": Do2(); break;
            case "3": Do3(); break;
        }
    }

    private void Do1() { }
    private void Do2() { }
    private void Do3() { }
}

再次使用它,以防你的真实代码更复杂。

答案 3 :(得分:1)

我会使用IEnumerable的元组集合和Action delegate来定义要调用的方法列表,将列表创建为私有字段或类初始化器,或者要灵活地添加元组到根据需要提供公共财产。如果需要传入参数,请使用Action委托的一个重载版本,即:Action(t1,t2)等。

如果您需要返回值,请根据其他答案使用Func delegate

        IEnumerable<Tuple<string, string, Action>> actions = new List<Tuple<string, string, Action>>() { 
        Tuple.Create<string, string, Action>("A", "1", SomeMethod1), 
        Tuple.Create<string, string, Action>("A", "2", SomeMethod2) 
        };

        string x = "A";
        string y = "2";

        var action = actions.FirstOrDefault(t => ((t.Item1 == x) && (t.Item2 == y)));

        if (action != null)
            action.Item3();
        else
            DoSomeDefaultMethod();


        public void SomeMethod1() { // Whatever you want to do  }
        public void SomeMethod2() { // Whatever you want to do  }

        public void DoSomeDefaultMethod() { // Default Method  } 

答案 4 :(得分:0)

如果您不想更改当前结构的大部分内容(并且不想创建新类型等),请考虑这一点。

将它们添加到下面的元组

var tuples = new List<Tuple<string,string,Func<>>()>(); // Func should be of your Do() type

将带有相关func的条件数据添加到列表

tuples.Add(new Tuple<string,string,Func<>>("A","1", Do1()));
...

只需在需要时使用条件直接调用

var function = tuples.Where(x => x.item1 == "A" && x.item2 == "1").Select(x => x.item3);
function.Invoke(); // to call it.

现在,如果您将来有更多的条件,您只需将它们添加到列表中,而无需更改任何代码。

答案 5 :(得分:0)

使用这样的东西。如果愿意,只有三个。

if (x == "A")
{
 int a = (y == "1") ? do1() : ((y == "2") ? do2() : do3());
}
}
    int do1() { return 10; }
    int do2() { return 10; }
    int do3() { return 10; }

答案 6 :(得分:-1)

我想在代码中的多个位置执行相同类型的开关,如果这样,请重构它并使用polymorphism instead

如果X是字符串优先replace the typecode with class并使用多态。