如何重构使用嵌套if-elses的代码?

时间:2019-05-03 06:16:25

标签: c# nested-if

我有一些用C#编写的代码,需要为此添加一些条件。从我的一个方法中,我调用了另一个方法“ UpdateData()”,该方法将一些数据更新到数据库中。现在,我需要添加一些条件。

  1. 配置文件中将存在appsetting,这是一个布尔值。如果值为true,则必须检查point2中的条件;如果值为false,则必须直接调用UpdateData()方法。
  2. 如果point1为true,则需要检查的类型和状态很少。

    条件1:如果类型为“ A”且状态为“已完成”,则调用“ UpdateData()”。

    条件2:如果类型为'B'并且状态为“ Complete”或“ Partial”或“ some xyz”,则调用“ UpdateData()”。

为此,我编写了以下代码:

 bool checkStatus = Convert.ToBoolean(ConfigurationManager.AppSettings["CheckStatus"]);

if (checkStatus)
{
   if (type == "A" && status == "Complete")
   {
      UpdateData();
   }
   else if (type == "B" && (status == "Complete" || status == "Other status" || status == "someother status"))
   {
      UpdateData(); // for type B , data should not be updated if status is anything other than those in condition.
   }
}
else
{
   UpdateData();
}

这按预期工作。但是我不想写嵌套的if-else。如果明天还有其他状态和类型需要添加,则需要在此处添加其他if条件。

有没有更好或更优化的书写方式?

6 个答案:

答案 0 :(得分:3)

我个人认为您所拥有的很好。但是,如果您真的不喜欢它,则可以尝试使用本地方法

bool CheckA() => type == "A" && status == "Complete";
bool CheckB() => type == "B" && (status == "Complete" || status == "Other status" || status == "someother status")

if (!checkStatus || CheckA() || CheckB())
   UpdateData();

bool Check(string val, params string[] list) => type == val && list.Contains(status);

// uglay, yet approachable
if (!checkStatus ||
    Check("A", "Complete") ||
    Check("B", "Complete", "Other status", "someother status"))
{
   UpdateData();
}

注意 :虽然可能是您喝杯茶,但我个人不会这样做 < / p>

答案 1 :(得分:0)

如果要优化快速添加新对象的能力,我会将其放入数组中。

bool[] checks = new bool[]{
    (type == "A" && status == "Complete"),
    (type == "B" && (status == "Complete" || status == "Other status" || status == "someother status"))
}

if (!checkStatus || checks.Contains(false)) //'Contains' requires Linq, it also works with 'checks.Any(c => !c)'
{
    UpdateData();
}

这样,您只需要在bool数组中添加一个新条件,而不必更新它的if语句。如果不需要,您可以快速将其注释掉。
但是,它的用处取决于您可能希望添加多少条件。

答案 2 :(得分:0)

为了避免嵌套错误,我通常会反转if条件,并尽早退出。如果可能的话,如下所示:

bool checkStatus = Convert.ToBoolean(ConfigurationManager.AppSettings["CheckStatus"]);

if (!checkStatus)
{
    UpdateData();
    return;
}

if (type == "A" && status == "Complete")
{
    UpdateData();
}
else if (type == "B" && (status == "Complete" || status == "Other status" || status == "someother status"))
{
    UpdateData(); // for type B , data should not be updated if status is anything other than those in condition.
}

答案 3 :(得分:0)

我想这段代码的重点是要确保更新在满足条件时运行,这是通过单元测试完成的。

因此,我将研究如何以一种可测试的方式编写此代码,以便确保它能做到如表所示。

一种实现方法可能是这样的:

public bool AppSettingsRunStatusMet(string appSettingsCheckStatus)
{
    return Convert.ToBoolean(appSettingsCheckStatus);
}

public bool TypeARunStatusMet(string type, string status)
{
   return (type.Equals("A")  && status.Equals("Complete"))
}

public bool TypeBRunStatusMet(string type, string status)
{
   return (
       type.Equals("B") && 
       ( 
            status.Equals("Complete") || 
            status.Equals("Other status") || 
            status.Equals("someother status")
       )
}

这已开始成为规则引擎,您可以根据需要设置任意数量的规则

每个if语句现在都可以调用一个方法,并且每个规则都在其自己的方法中分开,可以轻松地对其进行正确测试。

您可以将所有规则放在自己的类中,让引擎返回状态,如果该状态为true,则运行更新。主要思想是将配置代码与状态分析以及运行更新并执行所需操作的代码分开。

答案 4 :(得分:0)

我宁愿做这样的事情,以便在出现新案例或验证条件更改时,我们可以将新案例列入白名单。这是简单/可维护的,非常适合不断变化的有效案例集。

using System;
using System.Collections.Generic;

public class Program
{
      class Case{
        string type;
        string status;
         public Case(string type_val, string status_val ){
              status = status_val;
             type = type_val;
         }

        public override int GetHashCode()  
        {  
            return type.GetHashCode()+status.GetHashCode();  
        }  
        public override bool Equals(object obj)  
        {  
            Case test = obj as Case;  
            if (test== null)  
                return false;  
            return type == test.type &&  status == test.status ;  
        } 

    }
    public static void Main()
    {
        bool checkStatus = true;
        HashSet<Case> vaild_cases = new HashSet<Case>();
        vaild_cases.Add(new Case("A","Complete"));
        vaild_cases.Add(new Case("B","Complete"));
        vaild_cases.Add(new Case("B","Other status"));
        vaild_cases.Add(new Case("B","someother status"));
        Case current_case = new Case("A","Complete");
        if (!checkStatus || vaild_cases.Contains(current_case))
            UpdateData();
    }

    static void UpdateData()
    {
        Console.WriteLine("Hello, World!");
        return;
    }
}  

干杯!

答案 5 :(得分:0)

另一种选择是

if((new string[] {"Complete", "Other status", "someother status"}.Contains(status) && type == "B") ||
   (status == "Complete" && type == "A") ||
   !checkStatus)
{
    UpdateData();
}