如何以不同的顺序执行两个代码片段?

时间:2011-11-25 13:05:00

标签: c# .net if-statement

我有一个带有下一个逻辑的代码:如果某个布尔标志为真,则必须先执行两个代码片段中的一个,反之亦然。但是他们两个都必须永远执行。不幸的是,C#没有这方面的语义指令,如下所示:

if (condition) first
{
//Some code to execute first if condition is true
}
second
{
//Some code to execute first if condition is false
}

现在,我这样做:

if (condition)
{
//Code 1
//Code 2
}
else
{
//Code 2
//Code 1
}

这样的必要性很多,这会产生许多代码重复。可能有更好的解决方案吗?

7 个答案:

答案 0 :(得分:3)

将代码放入单独的方法

public void MyMethod1
{
   //first code goes here
}

public void MyMethod2
{
   //second code goes here
}


if (condition)
{
  MyMethod1();
  MyMethod2();
}
else
{
  MyMethod2();
  MyMethod1();
}

这样您就不必复制方法中的代码了。

答案 1 :(得分:2)

您可以考虑编写如下方法:

public static void DoBoth(Action first, Action second, bool keepOrder)
    {
        if (keepOrder)
        {
            first();
            second();
        }
        else
        {
            second();
            first();
        }
    }

答案 2 :(得分:1)

我用“代码1”和“代码2”创建了两个方法,然后像第二个选项那样继续:

if (condition)
{
Code1(); Code2();
}
else
{
Code 2(); Code1();
}

您还可以通过操作或代理对此进行修改,具体取决于“代码1”和“代码2”。

答案 3 :(得分:1)

我同意@Steven Jeuris关于更愿意了解潜在原因的评论,因为它可能指向需要改进的设计决策。但是,如果你需要坚持使用你拥有的东西,我会建议一个代理队列,因为你暗示你的例子与实际代码库相比非常简单。如果没有,那么其他一个答案就可以了,但随着复杂性的增加,下面的内容可能更容易维护。

注意:我将此作为示例 - GetQueue的参数及其内部的逻辑可以根据您的实际情况而改进。

public Queue<Action> GetQueue(bool condition)
{
    var toReturn = new Queue<Action>();
    if (condition)
    {
        toReturn.Enqueue(DoWork1);
        toReturn.Enqueue(DoWork2);
    }
    else
    {
        toReturn.Enqueue(DoWork2);
        toReturn.Enqueue(DoWork1);
    }
    return toReturn;
}

public void MyExecutingMethod()
{
    foreach (var action in GetQueue(true))
    {
        action();
    }
}

public void DoWork1()
{

}

public void DoWork2()
{

}

答案 4 :(得分:1)

您应该尽可能避免代码重复。在你的情况下,基本的想法是尝试提取似乎不止一次的所有内容,并试图将它“放”到你只需要写一次的地方。

在您的情况下,请说我们有以下内容:

 public void Bar()
 {
     ...
     if (condition)
     {
         //code for action 1
         //code for action 2
     }
     else
     {
         //code for action 2
         //code for action 1
     }
     ...
 }

 public void Foo()
 {
     ...
     if (condition)
     {
         //code for action 1
         //code for action 2
     }
     else
     {
         //code for action 2
         //code for action 1
     }
     ...
 }

现在我们显然可以看到你在这里有一些代码重复。我们可以通过以下方式改进:

 public void Bar()
 {
     ...
     if (condition)
     {
         Action1();
         Action2();
     }
     else
     {
         Action2();
         Action1();
     }
     ...
 }

 public void Foo()
 {
     ...
     if (condition)
     {
         Action1();
         Action2();
     }
     else
     {
         Action2();
         Action1();
     }
     ...
 }

 private void Action1()
 {
     //code for action 1
 }

 private void Action2()
 {
     //code for action 1
 }

这看起来好多了(特别是如果Action1代码和Action2代码很长)。我们现在设法只编写Action1Action2的代码,无论我们的代码中有多少FooBar样式方法。但我们仍然可以做得更多。你可以看到我们仍在复制一些令人讨厌的冗长代码。所以我们可以更进一步,做到以下几点:

 public void Bar()
 {
     ...
     DoAction(condition);
     ...
 }

 public void Foo()
 {
     ...
     DoAction(condition);
     ...
 }

 private void Action1()
 {
     //code for action 1
 }

 private void Action2()
 {
     //code for action 1
 }

 private void DoAction(bool condition)
 {
      if (condition)
      {
           Action1();
           Action2();
      }
      else
      {
           Action2();
           Action1();
      }
 }

现在,恕我直言看起来好多了。我们不仅仅设法编写Action1Action2特定代码一次,我们现在也设法只编写那个讨厌的方法排序逻辑。

这对可读性和最重要的可维护性产生了巨大影响。例如,如果在Action1中出现错误,您现在只需要在一个地方更改它。在原始实现中,您必须检查所有代码并在任何地方修复错误。

另外,想象一下方法排序依赖于业务规则,而你的客户端(哦,我的惊喜!)决定改变它们。使用最新的实现,您只需要在一个位置更改代码。

经验法则:尽可能避免代码重复,它会大大减少你输入的代码,以及你或者一些不良灵魂在不久的将来会遇到的麻烦。

答案 5 :(得分:0)

我将冒险猜测code1要么没有副作用,要么对类成员变量采取行动,在这种情况下,它们可以包含在返回void的方法中。然后,您可以按照以下方式执行某些操作:

...
    if (condition)
        DoWork(() => Code1(), () => Code2());
    else
    {
        DoWork(() => Code2(), () => Code1());
    }
...

private void Code1()
{
    // Code 1
}

private void Code2()
{
    // code 2
}

private void DoWork(Action action1, Action action2)
{
    action1();
    action2();
}

答案 6 :(得分:0)

我提出了另一个建议(伪代码)。

编辑:这取决于您的情况,您将采取哪种方法。这种方法的好处是简单性和灵活性。通过灵活性,我的意思是订单的决定现在与代码分开,因此您可以轻松地执行诸如添加新订单之类的操作,或者让订单以其他方式指定(例如,如果您现在想要将不同的订单与基于属性文件的不同用户)?

if(condition)
       runOrder = [ "one", "two" ];
else
       runOrder = [ "two", "one" ];

for(x=0; x<runOrder.length; x++)
{
     codeToRun = runOrder[x];
     switch(codeToRun)
     {
              Case "one": Code1();
              Case "two": Code2();
     }
}