1

我已经尝试了很多次,似乎只是在旋转我的轮子。我如何正确地将税级和金额写成人们可以输入不同收入金额的变量,并在代码中进行计算,而不是像我在代码中那样写出来?

我能够在我想要达到的目标方面取得更多进展。我需要有关如何分配这些变量以及如何正确编写输出的帮助。

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 Part_B_TaxBracket
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
        }

        private void btnCalculate_Click(object sender, EventArgs e)
        {
            //variables
            string status;
            string incomeasstring;
            string rateasstring;
             
            double income;  //to be input 
            double rate;     //to be calculated
            double tax;   //to be calculated

            double result;  // to be calculated            
            
           //process input
           if(status == "single")
            {
                if(income <= 9275)
                {
                    result = (income * .10);
                }
                if (income >= 9276 && income <= 37650)
                {
                    result = (income * .15);
                }
            }
            if (status == "married")
            {
                if (income <= 18550)
                {
                    result = (income * .10);
                }
            }
            if(income >=18551 && income <= 75300)
            {
                    result = (income * .15);
            }
        }
            //output the results
            lblresult.Text  = ("Your tax rate is {0} and taxes owed of {1}.", rate, tax);

        }
    }
}
4

3 回答 3

0

首先,我建议将税率计算提取到它自己的方法中。这将使事情保持清洁并启用该方法的早期返回,从而允许我们删除一堆else语句。只要我们按顺序检查范围(升序或降序),我们就不需要检查两个边界(即>= x && <= y)。这也使方法可测试,这是您应该始终考虑的 - 按钮单击的事件处理程序不是非常可测试的。*

其次,我建议您decimal用于货币计算而不是 double. 有关原因的更多信息,请参阅此答案(由 Jon Skeet 撰写)和此问题它是重复的)。但是我会注意到,由于这看起来像是一个学习练习,double应该没问题。但是请记住,您通常不希望将它们用于货币计算。

让我们定义我们的方法。它将接受status和我们的income. 它将验证状态是一个有效值(而不是说,Head Of Household),否则抛出异常。然后我们可以按顺序处理每个范围,return而不需要嵌套else语句:

public static decimal GetTaxRate(string status, decimal income)
{
    // we need to validate we have an appropriate status
    var comp = StringComparison.OrdinalIgnoreCase;

    if (!string.Equals(status, "married", comp) && !string.Equals(status, "single", comp))
        throw new InvalidOperationException("Invalid Status");

    if (string.Equals(status, "single", comp))
    {
        // note lack of "else" since we early return
        // note lack of " && income >= " which is implied
        if (income <= 9725) return 0.1m;
        if (income <= 37650) return 0.15m;
        if (income <= 91150) return 0.25m;
        if (income <= 190150) return 0.28m;
        if (income <= 413350) return 0.33m;
        if (income <= 415050) return 0.35m;

    }
    else // married
    {
        if (income <= 18550) return 0.1m;
        if (income <= 75300) return 0.15m;
        if (income <= 151900) return 0.25m;
        if (income <= 231450) return 0.28m;
        if (income <= 413350) return 0.33m;
        if (income <= 415050) return 0.35m;
    }

    // default for both
    return 0.396m;
}

现在我们可以从您的按钮单击事件处理程序中调用此函数:

string status = "single"; // get this some how
string incomeAsString = "1234.56"; // get this value some how

// validate that the income is a valid value
decimal income;
if (!decimal.TryParse(incomeAsString, out income)) 
{
   lblresult.Text = "Entered income is not a valid decimal value";
   return;
}

decimal taxRate = GetTaxRate(status, income); // calculate tax rate    
decimal totalTax = taxRate * income;

lblresult.Text = string.Format("Your tax rate is {0:P2} with taxes owed of {1:C2} (on income of {2:C2})", taxRate, totalTax, income);

我建议寻找对变量进行去字符串化的方法。status您可以使用 anenum来表示不同的状态。如果您只计划拥有这两个选项,您甚至可以使用 a bool isSingle(尽管我不喜欢该选项)。

如果你想使用一些 C#8 特性,我们可以使用递归模式匹配switch语句。我还在这里使用 C#7数字分隔符( _) 使数字更易于阅读:

// warning C# 8.0+
public static decimal GetTaxRate(string status, decimal income)
{
    // note: validation elided
    switch (status.ToLower(), income)
    {
        case ("single", decimal s) when s <= 9_725:
        case ("married", decimal m) when m <= 18_550:
            return 0.1M;
        case ("single", decimal s) when s <= 37_650:
        case ("married", decimal m) when m <= 75_300:
            return 0.15M;
        case ("single", decimal s) when s <= 91_150:
        case ("married", decimal m) when m <= 151_900:
            return 0.25m;
        case ("single", decimal s) when s <= 190_150:
        case ("married", decimal m) when m <= 231_450:
            return 0.28m;
        case (_, decimal i) when i <= 413_350:
            return 0.33m;
        case (_, decimal i) when i <= 415_050:
            return 0.35m;
        default:
            return 0.396m;
    }
}

在 C#9中,我们将能够在表达式中使用关系模式switch(参见SharpLab 示例

// warning C# 9.0
public static decimal GetTaxRate(string status, decimal income)
{
    // note: validation elided
    if (string.Equals(status, "single", StringComparison.OrdinalIgnoreCase))
    {
        return income switch {
            <= 9725 => 0.1M,
            <= 37650 => 0.15M,
            <= 91150 => 0.25M,
            <= 190150 => 0.28M,
            <= 413350 => 0.33M,
            <= 415050 => 0.35M,
            _ => 0.396M // default  
        };
    }
    
   // married
   return income switch {
        <= 18550 => 0.1M,
        <= 75300 => 0.15M,
        <= 151900 => 0.25M,
        <= 231450 => 0.28M,
        <= 413350 => 0.33M,
        <= 415050 => 0.35M,
        _ => 0.396M // default     
    };
}

注意mandM是用于指定decimal 文字的后缀。外壳无关紧要——它们是可以互换的

* 可以手动测试和验证事件处理程序(有人盯着标签文本),但理想情况下,您希望能够使用极点 xUnit 工具来定义自动化案例。

于 2020-07-04T12:36:50.773 回答
0

如果你只是想让你的代码看起来更好:

  • 首先,如果状态是已婚,您可以做的是将收入除以二,这样您就不会每次都检查状态和收入;

  • 其次,如果您使用“else if”而不是 if,您将获得更简洁的代码。你先检查收入是否低于9275,然后如果你输入“else if”,它就会知道收入高于9275,以此类推。

- - - - - - - - - - - 编辑 - - - - - - - - - - - -

问题是,这个税级或税率是无法计算的,你只能根据收入来决定。所以无论如何,你都会有这么多的 if 语句来决定利率。

现在我看到所欠税款是收入 * 税率,所以我不能在一开始将收入除以 2。我能做的是有一个单独的变量,incomePerPerson,并将其设为收入 / 2,以帮助减少每个 if 中的代码。

最后,您计算税收并在标签中显示该文本:

        double income = double.Parse(txtIncome.Text);
        string status = txtStatus.Text;

        //to be calculated
        double rate;
        double tax;
        double incomePerPerson = income;

        //get the income per person if status is married
        if (status == "married")
            incomePerPerson = income / 2;

        //determine tax rate
        if (incomePerPerson <= 9275)
        {
            rate = 0.10;
        }
        else if (incomePerPerson <= 37650)
        {
            rate = 0.15;
        }
        else if (incomePerPerson <= 91150)
        { 
            rate = 0.25;
        }
        else if (incomePerPerson <= 190150)
        {
            rate = 0.28;
        }
        else if (incomePerPerson <= 413350)
        {
            rate = 0.33;
        }
        else if (incomePerPerson <= 415050)
        {
            rate = 0.35;
        }
        else
        {
            rate = 0.396;
        }

        //determine taxes
        tax = income * rate;

        //output the results
        lblresult.Text  = ("Your tax rate is {0} and taxes owed of {1}.", rate, tax);

如果您找到了一种根据人均收入计算费率的方法,那么需要用该公式替换那些 if 语句。我想不出一个,所以这是你的作业:) 如果没有公式,我认为这是你能写的最干净的代码。

于 2020-07-03T18:57:25.627 回答
-1

我没有 C#,但我以前用 C 编程过,我知道你有一个 Switch 命令可用,我会推荐它。您设置了开关,以便首先测试最高值,然后逐步降低最大值。

这是 PowerShell 中的一些示例代码,它与 C# 很接近,它列出了逻辑。

$Status = "single"
$income = 190151

If ($Status -eq "single") {
  Switch ($income) {
   {$_ -gt 415050 } { "Tax bracket is 39.6%";Break}
   {$_ -gt 413350 } { "Tax bracket is 35% with taxes of 144,672.85" ; Break }
   {$_ -gt 190150 } { "Tax bracket is 33% with taxes of  82,500.00" ; Break }
   Default { "Table Not Complete"}
  }

}
Else {
  #*** Married Code Here ***
}

注意 $_ 是 $Income 的 PowerShell 快捷方式,您当然必须适应 C#

HTH

于 2020-07-03T19:34:05.600 回答