对于在程序中实现逻辑的If else,更好的选择是什么? | C#

时间:2016-07-10 19:28:59

标签: c# if-statement methods

我正在构建一个自动应用程序,允许用户从复选框等中选择选项,并在最后显示费用。

问题是我完成这个应用程序的方式很尴尬。例如,请参阅我的if else语句,他们不会涵盖决策的各个方面。

例如,这是我的代码的一部分

private decimal RushesMethod(out decimal radiatorRush_var, out decimal transmissionFlush_var, out decimal both_var)
        {
            radiatorRush_var = 0m;
            transmissionFlush_var = 0m;
            both_var = 0m;

            if (radiatorRushCheckBox.Checked)
            {
                radiatorRush_var = 30.00m;  
            }

            else if (transmissionFlushCheckBox.Checked)
            {
                transmissionFlush_var = 80.00m;  
            }

            else if (radiatorRushCheckBox.Checked && transmissionFlushCheckBox.Checked)
            {
                radiatorRush_var = 30.00m;
                transmissionFlush_var = 80.00m;            
                both_var = radiatorRush_var + transmissionFlush_var;
            }

            return both_var + transmissionFlush_var + radiatorRush_var;


        }  

如果用户选择radiatorRushCheckBox.Checked选项以及其他一些选项,而不是此方法,请说oilChangeCheckBox.Checked,那么我将如何涵盖所有该决定。对于所有人来说,if else语句是一种过于冗长的方式,因为谁知道用户选择了什么。

如果我选择所有选项然后它没有显示正确的价格,会发生以下情况。

enter image description here

以下是完整的应用程序代码:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace Automative_APP
{
    public partial class automativeForm : Form
    {
        public automativeForm()
        {
            InitializeComponent();
        }

        private void ClearOilLube()
        {

            oilChangeCheckBox.CheckState = CheckState.Unchecked;
            lubeJobCheckBox.CheckState = CheckState.Unchecked;
        }

        private void ClearFlushes()
        {
            radiatorRushCheckBox.CheckState = CheckState.Unchecked;
            transmissionFlushCheckBox.CheckState = CheckState.Unchecked;
        }

        private void ClearMisc()
        {
            inspectionCheckBox.CheckState = CheckState.Unchecked;
            replaceMufflerCheckBox.CheckState = CheckState.Unchecked;
            tireRotationCheckBox.CheckState = CheckState.Unchecked;
        }

        private void ClearOthers()
        {
            partsTextBox.Text = "";
            laborTextBox.Text = "";
        }

        private void ClearFees()
        {
            serviceLaborAnsLabelBox.Text = "";
            partsSummaryAnsLabelBox.Text = "";
            taxPartsAnsLabelBox.Text = "";
            totalFeesAnsLabelBox.Text = "";          
        }






        private decimal TotalCharges()
        {
            decimal rushesVar = RushesMethod();
            decimal oiLAndLubeVar = OilLubeCharges();
            decimal miscVar = MiscMethod();
            decimal partsLaborVar = PartsLaborMethod();
            decimal storeTaxCharges = TaxCharges();
            decimal totalSum;
            decimal totalSum1;

            totalSum1 = (rushesVar + oiLAndLubeVar + miscVar);


            totalSum = (rushesVar + oiLAndLubeVar + miscVar + partsLaborVar);


            partsSummaryAnsLabelBox.Text = partsLaborVar.ToString();

            partsSummaryAnsLabelBox.Text = partsTextBox.Text;

            serviceLaborAnsLabelBox.Text = "Total Services fee is " + " " + totalFeesAnsLabelBox.Text + " " + "and Labor amount is" + " " + laborTextBox.Text;

            taxPartsAnsLabelBox.Text = storeTaxCharges.ToString();

            return totalSum;

        }





        private decimal TaxCharges()
        {
            const decimal PARTS_TAX_VAR = 0.6m;
            decimal storeTax;
            decimal taxCal;


            storeTax = decimal.Parse(partsTextBox.Text);
            taxCal = PARTS_TAX_VAR * storeTax;

            return taxCal;


        }



        private decimal PartsLaborMethod()
        {
            decimal PL=0m;
            decimal labor;
            decimal totalPL = 0m;

            PL = decimal.Parse(partsTextBox.Text);         
            labor = decimal.Parse(laborTextBox.Text);

               totalPL= PL* labor;

               return totalPL;
        }



        private decimal MiscMethod()
        {
            decimal valueTotal2 = 0m;

            if (inspectionCheckBox.Checked && replaceMufflerCheckBox.Checked && tireRotationCheckBox.Checked)
            {
                valueTotal2 += (15.00m + 100.00m + 20.00m);
            }

            else if (inspectionCheckBox.Checked)
            {
                valueTotal2 += 15.00m;
            }

            else if (replaceMufflerCheckBox.Checked)
            {
                valueTotal2 += 100.00m;
            }

            else if (tireRotationCheckBox.Checked)
            {
                valueTotal2 += 20.00m;
            }

            return valueTotal2;


        }






          private decimal RushesMethod()
        {
            decimal valueTotal = 0m;

            if (radiatorRushCheckBox.Checked)
            {
                valueTotal += 30.00m;  
            }

            else if (transmissionFlushCheckBox.Checked)
            {
                valueTotal += 80.00m;  
            }

            else if (radiatorRushCheckBox.Checked && transmissionFlushCheckBox.Checked)
            {

                valueTotal += (80.00m + 30.00m);
            }

            return valueTotal;


        }


        private decimal OilLubeCharges()
        {

            decimal valueTotalOL=0m;

            if (oilChangeCheckBox.Checked && lubeJobCheckBox.Checked)
            {
                valueTotalOL += (26.00m + 18.00m);

            }

            else if (oilChangeCheckBox.Checked)
            {
                valueTotalOL += 26.00m;

            }

            else if (lubeJobCheckBox.Checked)
            {
                valueTotalOL += 18.00m;
            }

            return valueTotalOL;            

        }


        private void partsSummaryLabelBox_Click(object sender, EventArgs e)
        {

        }

        private void taxPartsLabelBox_Click(object sender, EventArgs e)
        {

        }

        private void exitButton_Click(object sender, EventArgs e)
        {
            this.Close(); //close the form
        }

        private void calculateButton_Click(object sender, EventArgs e)
        {

           decimal totalStore= TotalCharges();

           totalFeesAnsLabelBox.Text = totalStore.ToString();


        }

        private void clearButton_Click(object sender, EventArgs e)
        {
            ClearOilLube();
            ClearFlushes();
            ClearMisc();
            ClearOthers();
            ClearFees();
        }
    }
}
  

编辑:

这是问题所在,

The application should have the following value-returning methods:
• OilLubeCharges —Returns the total charges for an oil change and/or a lube job, if any.
• FlushCharges —Returns the total charges for a radiator flush and/or a transmission flush, if any.
• MiscCharges —Returns the total charges for an inspection, muffler replacement, and/or a tire rotation, if any.
• OtherCharges —Returns the total charges for other services (parts and labor), if any.
• TaxCharges —Returns the amount of sales tax, if any. Sales tax is 6% and is charged only on parts. If the customer purchases services only, no sales tax is charged.
• TotalCharges —Returns the total charges.
The application should have the following void methods, called when the user clicks the Clear button:
• ClearOilLube —Clears the check boxes for oil change and lube job.
• ClearFlushes —Clears the check boxes for radiator flush and transmission flush.
• ClearMisc —Clears the check boxes for inspection, muffler replacement, and tire rotation.
• ClearOther —Clears the text boxes for parts and labor.
• ClearFees —Clears the labels that display the labels in the section marked Summary  
  

最后,我使用 @ OmegaMan 解决方案完成了这项工作。我想   发布更改,以便它可以帮助任何人

我对TotalCharges()方法进行了更改。比较前一个和这个。

private decimal TotalCharges()
        {

            decimal total = 0.0m;

            if ( inspectionCheckBox.Checked)

            total +=  15.00m;

            if (replaceMufflerCheckBox.Checked)

                total += 100.00m;

            if (tireRotationCheckBox.Checked)

                total += 20.00m;

            if (oilChangeCheckBox.Checked)

                total += 26.00m;

            if (lubeJobCheckBox.Checked)
                total += 18.00m;

            if (radiatorRushCheckBox.Checked)

                total += 30.00m;

            if (transmissionFlushCheckBox.Checked)

                total += 80.00m;

            return total;  

我还更改了计算按钮CLICK EVENT HANDLER:

private void calculateButton_Click(object sender, EventArgs e)
        {

           decimal totalStore= TotalCharges();
            decimal taxCharge = TaxCharges();

           totalFeesAnsLabelBox.Text = (totalStore + taxCharge).ToString();
            taxPartsAnsLabelBox.Text = taxCharge.ToString();
            partsSummaryAnsLabelBox.Text = partsTextBox.Text;
            serviceLaborAnsLabelBox.Text = "The Total Service charges are" + totalStore + "and Labor is " + laborTextBox.Text;  

其余部分相同,逻辑成功。感谢所有贡献的人。

3 个答案:

答案 0 :(得分:3)

要最小化此操作,您可以创建Checkbox到decimal(Price)的映射。当您需要计算与选中复选框相关的价格时,您只能使用一行。

首先,创建一个映射变量并在某个时候填充它(对我来说,我选择了表单加载 - 你可以在InitializeComponent();之后在构造函数中完成它:

注意:将复选框重命名为有效复选框。

List<KeyValuePair<CheckBox, decimal>> checkboxPriceMapping;

private void Form1_Load(object sender, EventArgs e)
{
    checkboxPriceMapping = new List<KeyValuePair<CheckBox, decimal>>
    {
        new KeyValuePair<CheckBox, decimal>(checkBox1, 26.0m),
        new KeyValuePair<CheckBox, decimal>(checkBox2, 18.0m),
        new KeyValuePair<CheckBox, decimal>(checkBox3, 15.0m),
        new KeyValuePair<CheckBox, decimal>(checkBox4, 100.0m),
        new KeyValuePair<CheckBox, decimal>(checkBox5, 20.0m),
        new KeyValuePair<CheckBox, decimal>(checkBox6, 30.0m),
        new KeyValuePair<CheckBox, decimal>(checkBox7, 80.0m),
    };
}

然后,这是一种计算已检查控件总价的简单方法:

private decimal CalculateTotalPrice()
{
    return checkboxPriceMapping.Where(x => x.Key.Checked).Sum(x => x.Value);
}

答案 1 :(得分:3)

在一个单独的方法中汇总和集中总计操作,并在完成总和时检查每个复选框的状态:

public decimal TotalCosts()
{
    decimal total = 0.0m;

    if ({Oil Changed Checked})
       total += {Oil Cost};

    if ({Transmission checked})
       total += {Transmission total};

    if ({Repair Clutch})         
       total += {Clutch Cost}; // Maybe call a separate method ClutchTotal()?

     ... { Do this for all check boxes }

    return total;
}

不要尝试为不同的操作单独添加内容(就像使用both_var = radiatorRush_var + transmissionFlush_var;那样,这就是你的困惑。

有限状态机

我提到了有限状态机逻辑,它可用于组织任何代码。

想想自动售货机,它必须采用所有不同类型的硬币和美元钞票,并且在它可以提供产品之前它具有某些状态。 通过映射所有状态然后集中代码来处理每个状态,这将使代码bug免费且可维护。

如果有人在机器上添加一角硬币,状态从Welcome变为总计当前的硬币和美元但不提供产品。该状态为真,直到总数> 1。成本,然后命中Vend状态,分配产品。在完成Welcome的最后一步之前,它不会返回provide any monies if overpayment状态。

通过设置状态,您可以组织一个代码来处理您在应用中看到的所有情况。

答案 2 :(得分:2)

我使用http://www.michael-whelan.net/rules-design-pattern/将此业务规则设计应用于您的问题,这就是我想出的。使用此方法,您可以将每个购买案例抽象为自己的&#34;规则&#34;如果您需要根据订单状态进行更复杂的操作,只需添加新规则或对现有规则进行更改即可。

我还建议您添加某种类型的数据库,以保存您的价格,税率以及您将来可能需要摸索的其他任何数字,如果您还没有保存任何历史数据。

接口

public interface IExpenseRule
{
    decimal CalculateExpense(Order customerOrder);
}

代表订单状态

这代表我们订单的状态,并且是我们所有计算的真实来源。如果将来您需要更多属性以获得额外费用,那么可以从这里访问它们。例如,如果我想添加洗车,我可以在这里添加洗车标志,或者如果有洗涤水平则添加Enum。


    public class Order
    {
        public bool HasOilChange { get; set; }
        public bool HasLubeJob { get; set; }
        public bool HasRadiatorRush { get; set; }
        public bool HasTransmissionFlush { get; set; }
        public bool HasInspection { get; set; }
        public bool HasTireRotation { get; set; }
        public bool HasMufflerReplacement { get; set; }
        public decimal PartsCost { get; set; }
        public decimal LaborsCost { get; set; }
    }

订单的计算

以下是我们将规则应用于计算的地方。构造函数是将所有规则添加到规则集合的位置。 CalculateTotal迭代规则。规则只涉及它必须计算的任何项目。每个规则的结果都会加在一起以获得总数。 Sum方法是Linq扩展,用于将规则的结果一起添加。如果你愿意,可以使用for循环。

public class OrderCalculator
{
    List<IExpenseRule> rules = new List<IExpenseRule>();

    //all your rules get added here
    public OrderCalculator()
    {
        rules.Add(new OilChangeRule());
        rules.Add(new LubeJobRule());
        rules.Add(new TireRotationRule());
        rules.Add(new TaxOnPartsRule());
    }

//Runs all your calculations and returns the total based on the rules you feed and your order state
public decimal CalculateTotal(Order customerOrder)
{
    var total = 0m;
    total = rules.Sum(rule => rule.CalculateExpense(customerOrder));
    return total;
}

}

示例规则

有关规则的几个例子。如果我们有相互依赖的规则,我将其余部分作为OP的练习。

<pre><code>public class OilChangeRule : IExpenseRule
{
    public const decimal OilChangeCost = 26.00m;

    public decimal CalculateExpense(Order customerOrder)
    {
        return customerOrder.HasOilChange ? OilChangeCost : 0;
    }
}

public class LubeJobRule : IExpenseRule
{
    public const decimal LubeJobCost = 18.00m;

    public decimal CalculateExpense(Order customerOrder)
    {
        return customerOrder.HasLubeJob ? LubeJobCost : 0;
    }
}


public class TireRotationRule : IExpenseRule
{
    public const decimal TireRotationCost = 20.00m;

    public decimal CalculateExpense(Order customerOrder)
    {
        return customerOrder.HasTireRotation ? TireRotationCost : 0;
    }
}

public class TaxOnPartsRule : IExpenseRule 
{
    public const decimal TaxPercentageOnParts = 0.6m;

    public decimal CalculateExpense(Order customerOrder)
    {
        var taxOnParts = customerOrder.PartsCost * TaxPercentageOnParts;
        return taxOnParts;
    }
}</code></pre>

重构后的表单代码是什么

您的应用程序逻辑应该与任何UI分开。业务逻辑可以放入自己的dll中,并在之后的任何类型的应用程序中重用。 (是的,这段代码可能会进一步简化,但我认为这是相当简单明了的。)

public Order BuildOrder()
{
    var currentOrder = new Order();
    currentOrder.HasOilChange = oilChangeCheckBox.CheckState;
    currentOrder.HasLubeJob = lubeJobCheckBox.CheckState;
    currentOrder.HasRadiatorRush = radiatorRushCheckBox.CheckState;
    currentOrder.HasTransmissionFlush = transmissionFlushCheckBox.CheckState;
    currentOrder.HasInspection = inspectionCheckBox.CheckState;
    currentOrder.HasMufflerReplacement = replaceMufflerCheckBox.CheckState;
    currentOrder.HasTireRotation = tireRotationCheckBox.CheckState;
    currentOrder.PartsCost = Decimal.Parse(partsTextBox.Text);
    currentOrder.LaborsCost = Decimal.Parse(laborTextBox.Text);
    return order;
}

private void calculateButton_Click(object sender, EventArgs e)
{
   var totalCalculator = new OrderCalculator();
   var partsCalculator = new PartsCalculator();
   var serviceCalculator = new ServiceCalculator();
   var order = BuildOrder();
   var totalCost = totalCalculator.CalculateTotal(order);
   var partsCost = partsCalculator.CalculateTotal(order);
   var serviceCost = serviceCalculator.CalculateTotal(order);
   //Do what you need to with the totals here;
   totalFeesAnsLabelBox.Text = totalCost.ToString();
}