首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从抛出的异常恢复或返回

从抛出的异常恢复或返回
EN

Stack Overflow用户
提问于 2018-08-21 22:45:10
回答 4查看 622关注 0票数 1

多年来,我的主要语言是Perl,我定期对用户输入进行验证,没有任何问题。现在,我使用了大量的C#,并希望迁移到通过验证用户输入和从抛出的异常恢复/返回的抛出/捕获样式。我正在使用一种非常天真(即,愚蠢)的方法来做这件事,我觉得迫切需要转向一些更成熟、更不愚蠢的东西。我复制了一个从提示符返回整数的函数。我正在通过使用可怕的GOTO语句从用户错误中恢复。有什么更好的方法来做这件事?

谢谢,CC。

代码语言:javascript
复制
private static int GetInput(string v)
{
    begin:
    Console.Write(v);
    string strradius = Console.ReadLine();
    int intradius;
    try
    {
        intradius = int.Parse(strradius);
        if (intradius < 1)
            throw new ArgumentOutOfRangeException();
    }
    catch (ArgumentNullException)
    {
        Console.WriteLine("You must enter a value.");
        goto begin;
    }
    catch (FormatException)
    {
        Console.WriteLine("You must enter a valid number.");
        goto begin;
    }
    catch (ArgumentOutOfRangeException)
    {
        Console.WriteLine("Your number is out of range");
        goto begin;
    }
    catch (Exception ex)
    {
        Console.WriteLine(ex);
        goto begin;
    }
    finally
    {
        Console.WriteLine("Okay");
    }
    return intradius;
} 
EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2018-08-21 23:12:31

首先,关于何时使用goto的一个好的经验规则是永远不会的。真的,除了少数非常罕见的特殊情况外,你永远不会想要使用它。

接下来,对于您的问题,使用异常来验证输入通常是个坏主意。就像大多数人指出的那样,它很贵。例外情况应该用来处理特殊情况,所以我实际上根本不使用它们。

相反,您可以使用do-while循环,只要用户输入不正确的输入,就可以重复。一旦得到适当的输入,就退出循环。如果发生异常,则不应真正继续该过程。要么在外部处理它(即,方法中没有try-catch ),要么如果必须执行try-catch,那么只需打印一条消息并退出该方法。但是,对于这种方法,我不会使用异常处理。另外,将返回类型实际更改为bool也是一个好主意,因此您向外部世界表明该方法是否通过返回类型成功。您可以使用out参数实际返回转换后的int

代码语言:javascript
复制
private static bool GetInput(string msg, out int converted)
{
    bool result = false;
    converted = 0;
    do
    {
        Console.Write(msg);
        string str = Console.ReadLine();
        result = int.TryParse(str, out converted);
        if (result && converted < 1)
        {
            Console.WriteLine("Your number is out of range");
            result = false;
        }
        if (!result && string.IsNullOrEmpty(str))
        {
            Console.WriteLine("You must enter a value.");
        }
        if (!result && !string.IsNullOrEmpty(str))
        {
            Console.WriteLine("You must enter a valid number.");
        }
    } while (!result);

    return result;
}
票数 1
EN

Stack Overflow用户

发布于 2018-08-21 23:29:34

在C#代码中使用goto语句受到高度反对,因为它使代码难以读取、调试和维护(要获得更多信息,请阅读)。循环、if/ goto语句或方法调用可以用来代替goto语句。此外,try \ catch块应该被谨慎地使用,以捕获您无法处理的异常。

在您的例子中,我们可以使用一个while循环来继续循环,直到输入一个有效的数字,并且我们可以使用方法来尝试解析字符串并获得一个整数结果。此方法返回表示成功的Boolean,并接受将设置为整数结果的out参数。

我对您的方法的建议是让它接受一个字符串,该字符串将用作用户的提示符(要求他们输入一个数字),并返回输入的整数结果。

例如:

代码语言:javascript
复制
private static int GetIntFromUser(string prompt, int minValue = int.MinValue, 
    int maxValue = int.MaxValue)
{           
    int result;
    string errorMsg = $"ERROR: Input must be a valid number from {minValue} to {maxValue}";

    while(true)
    {
        Console.Write(prompt);
        string input = Console.ReadLine();

        if (!int.TryParse(input, out result) || result < minValue || result > maxValue)
        {
            Console.ForegroundColor = ConsoleColor.Red;
            Console.WriteLine(errorMsg);
            Console.ResetColor();
        }
        else
        {
            break;
        }
    }

    return result;
}

在实践中,我们现在可以调用此方法从用户那里获取数字,并且我们将知道它们是有效的,而无需进行任何额外的验证:

代码语言:javascript
复制
private static void Main()
{
    // Age must be between 5 and 100
    var age = GetIntFromUser("Please enter your age: ", 5, 100);

    // Weight must be a positive number (minimum of zero)
    var weight = GetIntFromUser("Please enter your weight: ", 0);

    // No restrictions on favorite number
    var favNum = GetIntFromUser("Enter your favorite whole number: ");

    // This is a similar method I wrote to pause the program with a prompt
    GetKeyFromUser("\nDone! Press any key to exit...");
}

输出

票数 1
EN

Stack Overflow用户

发布于 2018-08-21 23:15:42

我会这样写(虽然我可能会给用户一个放弃的机会):

代码语言:javascript
复制
 private static int GetInput(string v)
 {
     int intradius = 0;   //needs to be initialized to keep compiler happy
     while (true)
     {
         Console.Write($"{v}: ");
         string strradius = Console.ReadLine();
         if (!int.TryParse(strradius, out intradius))
         {
             Console.WriteLine($"An integer is required: [{strradius}] is not an integer");
         }
         else if (intradius < 1)
         {
             Console.WriteLine($"The entered number [{intradius}] is out of range, it must be one or greater");
         }
         else
         {
             break;      //breaking out of the while loop, the input is good
         }
     }

     return intradius;
 }
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51957673

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档