c# - 为什么在不应该抛出该异常时抛出该异常?

标签 c# exception console-application

我有以下(非常简单的)控制台计算器,可以进行基本的圆计算:

using System;

namespace Circle
{
    class Program
    {
        /* Compute the area of a cricle given its radius. */
        public static double Area(double radius)
        {
            return Math.Pow(radius, 2) * Math.PI;
        }

        /* Compute the circumference of a circle given is radius. */
        public static double Circumference(double radius)
        {
            return radius * 2 * Math.PI;
        }

        /* Compute the diameter of a circle given its radius. */
        public static double Diameter(double radius)
        {
            return radius * 2;
        }

        /* Report the result. */
        public static string Result(double radius, double area, double circumference, double diameter)
        {
            return "- A circle whose radius is " + radius + " has the following properties: "
                    + "\n- Area: " + area.ToString("0.##") + "\n- Circumference: " + circumference.ToString("0.##")
                    + "\n- Diameter: " + diameter.ToString("0.##");
        }

        static void Main(string[] args)
        {
            double radius = 0;
            char choice;
            while (true)
            {
            Calculate:
                {
                    // 1. Get the radius from the user. 
                    Console.Write("- Enter the radius of the circle: ");
                    try
                    {  // verify the input is of numerical type 
                        radius = Convert.ToDouble(Console.ReadLine());
                        if (radius <= 0)  // check for negative values 
                        {
                            Console.WriteLine(" [Error] Radius must be a positive value!");
                            Console.WriteLine();
                            continue;  // restart from the next iteration without executing the rest of the statements 
                        } // end if 
                    }
                    catch (FormatException e)
                    {
                        Console.WriteLine(" [Error] " + e.Message);
                        Console.WriteLine(); // skip a line
                        continue;  // restart from the next iteration without executing the rest of the statements 
                    } // end catch 
                }
                // 2. Calculate the area, circumference, and diameter of the circle. 
                double area = Area(radius);
                double circumference = Circumference(radius);
                double diameter = Diameter(radius);
                // 3. Display the results. 
                Console.WriteLine(Result(radius, area, circumference, diameter));
            // 4. Ask the user whether to quit.
            Ask:
                {
                    Console.Write("- Do you wish to make another calculation [Y or N]? ");
                    choice = Convert.ToChar(Console.Read());
                }
                if (choice.Equals('Y') || choice.Equals('y'))
                {
                    goto Calculate; // return to the beginning of the Calculate block. 
                }
                else if (choice.Equals('N') || choice.Equals('n'))
                {
                    break; // exit 
                }
                else {
                    Console.WriteLine("Invalid choice! Press Y to continue or N to exit.");
                    goto Ask; // return to the beginning of the Ask block. 
                }
            }  // end while 
            Console.WriteLine("Thank you for using me. Have a nice day!");
            Console.WriteLine();
        } // end Main 
    }
}

计算后,程序会询问用户是否希望进行另一次计算。如果用户输入 Y,程序会提示他们再次输入半径。如果用户输入 N,程序终止。

但是,有两个基本问题:

  1. 如果用户选择按 Y 进行另一次计算,程序会提示用户输入一个值,但还会执行 catch block 并抛出异常。这显示在示例输出中:
  • Enter the radius of the circle: 3

  • A circle whose radius is 3 has the following properties:

  • Area: 28.27

  • Circumference: 18.85

  • Diameter: 6

  • Do you wish to make another calculation [Y or N]? Y

  • Enter the radius of the circle: [Error] Input string was not in a correct format.

  • Enter the radius of the circle:

  1. 第二个问题是,当用户输入 Y 或 N 以外的内容时,程序也会出现意外行为,如输出所示:
  • Enter the radius of the circle: 4
  • A circle whose radius is 4 has the following properties:
  • Area: 50.27
  • Circumference: 25.13
  • Diameter: 8
  • Do you wish to make another calculation [Y or N]? j Invalid choice! Press Y to continue or N to exit.
  • Do you wish to make another calculation [Y or N]? Invalid choice! Press Y to continue or N to exit.
  • Do you wish to make another calculation [Y or N]? Invalid choice! Press Y to continue or N to exit.
  • Do you wish to make another calculation [Y or N]?

我似乎无法弄清楚为什么会发生这两种情况。我怀疑这是我对 gotocontinue 的使用,但我无法分辨。

最佳答案

问题是您的 Convert.ToChar(Console.Read())。它从输入中读取一个字符,但在按下回车之前不会从控制台设置输入。所以 Console.Read() 正确地获取了 'Y',但是输入有一个 ENTER 排队,所以你的 Convert。 ToDouble(Console.ReadLine()) 获取它尝试转换的空字符串,因此出现异常。

Convert.ToChar(Console.Read()) 更改为 Convert.ToChar(Console.ReadLine()) 并且它工作正常。

您还应该摆脱 goto 并摆脱异常陷阱 - 您应该改用 double.TryParse(...)。没有更多异常(exception)。


我对您的代码进行了重构以供您尝试 - 没有 goto 也没有异常处理。

while (true)
{
    while (true)
    {
        Console.Write("- Enter the radius of the circle: ");
        double radius;
        if (double.TryParse(Console.ReadLine(), out radius) && radius > 0.0)
        {
            double area = Area(radius);
            double circumference = Circumference(radius);
            double diameter = Diameter(radius);
            Console.WriteLine();
            Console.WriteLine(Result(radius, area, circumference, diameter));
            break;
        }
        Console.WriteLine(" [Error] Radius must be a positive value!");
        Console.WriteLine();
    }
    string choice = "";
    while (true)
    {
        Console.Write("- Do you wish to make another calculation [Y or N]? ");
        choice = Console.ReadLine();
        if (new [] { "Y", "N", }.Contains(choice.ToUpper()))
        {
            break;
        }
        Console.WriteLine();
        Console.WriteLine("- Invalid choice! Press Y to continue or N to exit.");
    }
    if (choice.ToUpper() == "N")
    {
        break;
    }
    Console.WriteLine();
}
Console.WriteLine();
Console.WriteLine("- Thank you for using me. Have a nice day!");
Console.WriteLine();

关于c# - 为什么在不应该抛出该异常时抛出该异常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35642762/

相关文章:

c# - 无法从 C# 设置 Word 样式的基本样式

c# - 如何管理装饰 ApiController 中的重复?

c# - 使用 Smo.Backup 将 SQL Server 数据库备份到字符串

java - 制作一个数组排序器

python - Python 中无法捕获的异常

c - 如何使用可以远程连接的控制台创建 linux C 应用程序

c# - 为什么 string.Equals 默认情况下不区分大小写?

.net - 为什么一些 .Net 异常以换行符结尾

C#包结构系统

c# - 从列表中打印出对象元素