如何避免多个嵌套的IF

F.P*_*F.P 19 c# design-patterns if-statement exception

我目前正在尝试将我的程序重组为更多OO并更好地实现已知模式等.

我有很多嵌套的IF语句,想要摆脱它们.我怎么能这样做?我的第一种方法是用异常完成它,例如

public static Boolean MyMethod(String param) {
 if (param == null)
  throw new NullReferenceException("param may not be null");

 if (param.Equals("none") || param.Equals("0") || param.Equals("zero"))
  throw new ArgumentNullException("param may not be zero");

 // Do some stuff with param
 // This is not executed if param is null, as the program stops a soon
 // as one of the above exceptions is thrown
}
Run Code Online (Sandbox Code Playgroud)

该方法用于本申请的主要类别,例如

static void Main() {
 try {
  Boolean test = MyClass.MyMethod(null); // Will throw an exception
 } catch (Exception ex) {
  MessageBox.Show(ex.Message, "Error");
 }
Run Code Online (Sandbox Code Playgroud)

我认为这是非常好的,因为它可以防止嵌套语句和几乎所有方法操作在一个级别上很好地排列.

与IF语句一样,该方法看起来像这样

public Boolean MyMethod(String param) {
 if (param != null) {
  if (!param.Equals("none") && !param.Equals("0") && !param.Equals("zero")) {
   // Do some stuff with param
  } else {
   MessageBox.Show("param may not be zero", "Error");
 } else {
  MessageBox.Show("param may not be null", "Error");
 }
}
Run Code Online (Sandbox Code Playgroud)

我发现非常非常难看并且难以维护.

现在,问题是; 这种做法好吗?我知道,这可能是主观的,但是你如何克服嵌套的IF(1或2级并不是那么糟糕,但之后会变得更糟......)

Ber*_*van 19

你的问题被称为箭头反模式.

有一些实用的方法,例如你在样本中展示的Guard语句,对整个设计模式,避免if(和其他)一起......

关于如何解决它们的大量资源:

http://www.codinghorror.com/blog/2006/01/flattening-arrow-code.html

http://www.lostechies.com/blogs/chrismissal/archive/2009/05/27/anti-patterns-and-worst-practices-the-arrowhead-anti-pattern.aspx

http://elegantcode.com/2009/08/14/observations-on-the-if​​-statement/


Fre*_*örk 16

这真的取决于他们的目的.在第一个示例中,if语句用于执行合同,确保方法的输入满足特定要求.在这些情况下,我自己的代码往往看起来很像你的代码.

在使用if块来控制方法流程(而不是强制执行合同)的情况下,有时可能会有点困难.有时我会遇到类似以下(极简化)示例的代码:

private void SomeMethod()
{
    if (someCondition == true)
    {
        DoSomething();
        if (somethingElse == true)
        {
           DoSomethingMore();
        }
    }
    else
    {
        DoSomethingElse();
    }
}
Run Code Online (Sandbox Code Playgroud)

在这种情况下,似乎该方法有几个职责,所以在这种情况下,我可能会选择将其拆分为几个方法:

private void SomeMethod()
{
    if (someCondition == true)
    {
        DoItThisWay();
    }
    else
    {
        DoSomethingElse();
    }
}

private void DoItThisWay()
{
    DoSomething();
    if (somethingElse == true)
    {
       DoSomethingMore();
    }
}
Run Code Online (Sandbox Code Playgroud)

这使得每个方法使用较少的嵌套代码更加简单,并且如果方法具有良好的名称,则还可以提高可读性.