重试直到用户输入正确

时间:2015-07-29 11:13:03

标签: c#

我正在通过Rob Miles Yellow Book学习C#,并且遇到了理解变量范围的问题。

我开发的课程(在底部)要求输入一个数字,然后将其显示给用户。我想增强它,以便如果用户输入10而不是10,它输出一条消息,并且用户有另一次尝试。

这是迄今为止在改变中的几次尝试之一...

...

    static int readInt(string prompt, int low, int high)
    {
        int result;

        do
        {
            try
            {
                string intString = readString(prompt);
                result = int.Parse(intString);
                Console.WriteLine("Thank you");
            }
            catch
            {
                Console.WriteLine("Invalid age value");
            }

        } while ((result < low) || (result > high));

        return result;
    }
...

不幸的是,这会影响(我认为)将result推出范围,因为通过此更改,我看到以下补充错误:

  

CS0165使用未分配的局部变量'result'

实现此目的的C#方式是什么?

完整的课程:

using System;

class Exception1
{
    static string readString(string prompt)
    {
        string result;

        do
        {
            Console.Write(prompt);
            result = Console.ReadLine();
        } while (result == "");

        return result;
    }

    static int readInt(string prompt, int low, int high)
    {
        int result;

        do
        {            
            string intString = readString(prompt);
            result = int.Parse(intString);            
        } while ((result < low) || (result > high));

        return result;
    }


    public static void Main()
    {
        const int SCORE_SIZE = 1;

        int[] scores = new int[SCORE_SIZE];

        for (int i = 0; i < SCORE_SIZE; i++)
        {
            scores[i] = readInt("Score : ", 0, 1000);

        }

        for (int i = 0; i < SCORE_SIZE; i++)
        {
            Console.WriteLine("Score " + i + " is " + scores[i]);
        }

        Console.Read();
    }
}    

4 个答案:

答案 0 :(得分:6)

编译器不知道while循环实际运行(它可以在分配result之前抛出和异常)并在result上设置一个值。因此它抱怨这一点。

您可以通过为result分配默认值来规避这一点:

int result = -1;

或者通过在catch块中设置值:

catch
{
    result = -1;
    Console.WriteLine("Invalid age value");
}

我总是在这些情况下使用-1作为此值的错误指示&#39;。

答案 1 :(得分:1)

除了Patrick Hoffman的答案,这是正确的,你应该考虑使用int.TryParse而不是int.Parse

对流控制使用异常处理通常是一个坏主意,这说明了其中一个原因。编译器正在识别在实际分配result之前可能发生异常(实际上,如果用户从未输入数值,则会发生这种情况)。它无法正确评估unassigend变量。如果您使用TryParse,则您不会遇到此特定问题。

只有当您意识到有一些因素无法控制或能够处理常规代码和检查(if (bTryParseReturn == false) ....)时,才应使用异常处理 - 当用户输入可能存在问题以至于没有例如,测试它的简单方法。即使这样,异常也会产生错误,而不只是再次尝试&#34;情况 - 完全可能的是,异常永远无法从中恢复或避免,特别是因为您正在捕获所有异常(而不仅仅是InvalidCastException或其他像那样)。例如,假设异常是System.OutOfMemoryException(用户试图在您的提示符下输入数据的数据)。从用户的角度来看,你的程序将会尝试快速而严重地崩溃。

答案 2 :(得分:1)

编译器无法保证设置属性结果,但仍希望在方法结束时输出结果。

可能会抛出异常或导致在到达方法的最后一行之前设置结果的各种其他问题。

因此编译器会抢占NullReferenceException场景并将其视为编译错误。

这对你有帮助:))

如前所述,为属性结果提供一个默认值来解决此问题。

如果属性处于类级别,则会隐式设置它的属性类型默认值 - 但这是另一个问题。

答案 3 :(得分:1)

如果您真的不想将结果设置为最初的任何值,只是想添加可能的解决方案:

Fragment

如果static int readInt(string prompt, int low, int high) { bool validInput; int result; do { if ((validInput = int.TryParse(readString(prompt), out result))) Console.WriteLine("Thank you"); else Console.WriteLine("Invalid age value"); } while (!validInput || (result < low) || (result > high)); } 失败,则结果将设置为整数默认值(0),TryParse变量将设置为false,因此循环将再次通过。