我正在使用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”,我的程序 通过在输入框中显示“无效输入”来处理异常输出框。但是,它会继续计算默认浮点类型的sin
或cos
(等)。所以输出框中的答案如下:“invalid input1”或“invalid input0”。我提供了截图:
我确实意识到这是因为我告诉它在调用get_input()
方法后立即附加文本,但我真的不知道如何找到解决方法。我尝试过以7种方式重构代码,但总会出错。
答案 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)
这是因为你无法告诉调用代码发生了错误。
有两种方法可以做到这一点。
现在将异常捕获,但将返回类型更改为可空浮点(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());
}
让异常传播到您的按钮点击代码。在这种情况下,您的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");
}
}
两种方法都可以,但第二种方法更清洁。
答案 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
中指出某些事情失败了。我提出了两种解决问题的方法:
使用 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());
}
}
我认为基于的方法是使用高阶方法:您为其提供委托的方法:
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));
}
因此,您在此方法中重用代码。这使得代码更容易调试。