如何重构这段代码?

时间:2016-01-17 18:17:16

标签: c#

我正在使用Visual C#设计一个简单的计算器,但我遇到了一个恼人的运行时错误(这对于静态类型语言来说很有趣)。

首先让我告诉你部分代码:

private float get_input()
{
    try
    {
        return float.Parse(textBox1.Text);
    }
    catch
    {
        textBox2.Clear();
        textBox2.AppendText("Invalid Input");
        return 0;
    }

}

private void button1_Click(object sender, EventArgs e)
{ 
    textBox2.Clear();
    float v = get_input();
    textBox2.AppendText((Math.Sin(v)).ToString());
}

问题在于,当我运行程序时,例如,我在输入框中输入“a”,我的程序 通过在输入框中显示“无效输入”来处理异常输出框。但是,它会继续计算默认浮点类型的sincos(等)。所以输出框中的答案如下:“invalid input1”或“invalid input0”。我提供了截图:

我确实意识到这是因为我告诉它在调用get_input()方法后立即附加文本,但我真的不知道如何找到解决方法。我尝试过以7种方式重构代码,但总会出错。

6 个答案:

答案 0 :(得分:9)

使用TryParse而不是try ... catch

private void button1_Click(object sender, EventArgs e)
{ 
    textBox2.Clear();
    float result;
    if (float.TryParse(textBox1.Text, out result))
    {
         textBox2.AppendText(Math.Sin(result).ToString());
    }
    else
    {
        textBox2.Text = "Invalid Input";
    }
}

答案 1 :(得分:2)

这是因为你无法告诉调用代码发生了错误。

有两种方法可以做到这一点。

  1. 现在将异常捕获,但将返回类型更改为可空浮点(float?)并在错误情况下将其设置为null

    private float? get_input()
    {
        try
        {
            return float.Parse(textBox1.Text);
        }
        catch
        {
            textBox2.Clear();
            textBox2.AppendText("Invalid Input");
            return null;
        }
    }
    

    然后你必须陷入这种状况:

    private void button1_Click(object sender, EventArgs e)
    { 
        textBox2.Clear();
        float? v = get_input();
        if (v != null) textBox2.AppendText((Math.Sin(v)).ToString());
    }
    
  2. 让异常传播到您的按钮点击代码。在这种情况下,您的get_input方法会成为一个班轮,可以删除:

    private void button1_Click(object sender, EventArgs e)
    { 
        textBox2.Clear();
        try
        {
            float v = float.Parse(textBox1.Text);
            textBox2.AppendText((Math.Sin(v)).ToString());
        }
        catch
        {
            textBox2.Clear();
            textBox2.AppendText("Invalid Input");
        }
    }
    
  3. 两种方法都可以,但第二种方法更清洁。

答案 2 :(得分:1)

这对你有用吗?在这样一个简单的场景中,我认为不需要单独的功能。

private void button1_Click(object sender, EventArgs e)
{ 
    textBox2.Clear();
    try
    {
        float v = float.Parse(textBox1.Text);
        textBox2.AppendText(Math.Sin(v).ToString());
    }
    catch
    {
        textBox2.AppendText("Invalid Input");
    }
}

如果你想拥有一个单独的功能,你可以这样做:

private float? try_get_input()
{
    try
    {
        return float.Parse(textBox1.Text);
    }
    catch
    {
        return null;
    }
}

private void button1_Click(object sender, EventArgs e)
{ 
    textBox2.Clear();
    float? v = try_get_input();
    if (v != null)
    {
        textBox2.AppendText(Math.Sin(v.Value).ToString());
    }
    else
    {
        textBox2.AppendText("Invalid Input");
    }
}

答案 3 :(得分:1)

如果在解析函数get_input中抛出异常,则返回值0。但是,调用函数button1_Click无法知道首先抛出了异常。

答案 4 :(得分:1)

这样的事,也许?

private bool try_get_input(out float val)
{
    val = 0;

    try
    {
        val = float.Parse(textBox1.Text);
        return true;
    }
    catch
    {
        textBox2.Clear();
        textBox2.AppendText("Invalid Input");
    }

    return false;
}

private void button1_Click(object sender, EventArgs e)
{ 
    textBox2.Clear();

    float v = 0;

    if (try_get_input(out v))
    {
        textBox2.AppendText((Math.Sin(v)).ToString());
    }
}

答案 5 :(得分:0)

问题是你并没有真正在get_input中指出某些事情失败了。我提出了两种解决问题的方法:

  1. 使用 NaN NaN代表非数字。例如,如果计算 2.0 的arcsin,则使用它。通常,NaN传播每个表达式。然后,您可以使用button1_Click方法检测它:

    private float get_input() {
        try {
            return float.Parse(textBox1.Text);
        }
        catch {
            textBox2.Clear();
            textBox2.AppendText("Invalid Input");
            return float.NaN;
        }
    }
    
    private void button1_Click(object sender, EventArgs e) { 
        textBox2.Clear();
        float v = get_input();
        if(v != float.NaN) {
            textBox2.AppendText((Math.Sin(v)).ToString());
        }
    }
    
  2. 我认为基于的方法是使用高阶方法:您为其提供委托的方法:

    private void calculateResult (Func<float,float> f) {
        textBox2.Clear();
        try {
            float v = float.Parse(textBox1.Text);
             textBox2.AppendText((f(v)).ToString());
        }
        catch {
            textBox2.AppendText("Invalid Input");
            return float.NaN;
        }
    }
    

    现在可以通过使用 lambda表达式简单地提供对Math.Sin的引用来调用该方法:

    private void button1_Click(object sender, EventArgs e) { 
        calculateResult(x => (float) Math.Sin(x));
    }
    

    此外,它是一个优雅的解决方案,因为您可以轻松枚举您想要实现的所有功能:

    private void button1_Click(object sender, EventArgs e) { 
        calculateResult(x => (float) Math.Sin(x));
    }
    
    private void button2_Click(object sender, EventArgs e) { 
        calculateResult(x => (float) Math.Cos(x));
    }
    
    private void button3_Click(object sender, EventArgs e) { 
        calculateResult(x => (float) Math.Tan(x));
    }
    

    因此,您在此方法中重用代码。这使得代码更容易调试。