C# 这是goto语句的一个好用法吗?

C# 这是goto语句的一个好用法吗?,c#,goto,C#,Goto,我正在编写一个简单的C#控制台应用程序,在该应用程序中,如果UserId的输入无效,我将使用GoTo语句返回到标签来解决问题 但是我不确定我是否正确地使用了这个语句。我想看看是否有更好的方法来解决这个问题,即使不使用GoTo语句 public void CreateAccount() { Console.WriteLine("----- Create New Account -----\n" + "Enter following accoun

我正在编写一个简单的C#控制台应用程序,在该应用程序中,如果UserId的输入无效,我将使用GoTo语句返回到标签来解决问题

但是我不确定我是否正确地使用了这个语句。我想看看是否有更好的方法来解决这个问题,即使不使用GoTo语句

public void CreateAccount()
{
    Console.WriteLine("----- Create New Account -----\n" +
        "Enter following account information:\n");

    getUserID:
    {
        Console.WriteLine("Enter a UserID (Alphanumeric; no special characters): ");
        string userid = Console.ReadLine();
        if (!ValidUserID(userid))
        {
            Console.WriteLine("Userid can only contain A-Z, a-z & 0-9. Try again");
            goto getUserID;
        }
        if (data.IsUserInFile(userid))
        {
            Console.WriteLine("Userid already exists. Try again");
            goto getUserID;
        }
    }
}

我将对其他字段(如Pin、AccountType、Balance、AccountStatus等)使用相同的方法。因此,在扩展其使用之前,我希望确保以正确的方式执行此操作。

一个简单的方法是使用if/else if/else构造:

public void CreateAccount()
{
    Console.WriteLine("----- Create New Account -----\n" +
        "Enter following account information:\n");

    string userid = null;
    while (true)
    {
        Console.WriteLine("Enter a UserID (Alphanumeric; no special characters): ");
        userid = Console.ReadLine();
        if (!ValidUserID(userid))
        {
            Console.WriteLine("Userid can only contain A-Z, a-z & 0-9. Try again");
        }
        // if the condition above isn't matched, we'll check this condition
        else if (data.IsUserInFile(userid))
        {
            Console.WriteLine("Userid already exists. Try again");
        }
        // if that isn't matched either, then we have an acceptable userid and can exit the loop
        else
        {
            break;
        }
    }
}
注意,我已经将
userid
声明移出了循环,因为您可能需要在循环之后使用它

或者,您可以进一步分解代码。读取用户ID的整个方法可以移到自己的方法中:

public string ReadUserId()
{
    while(true)
    {
        // Prompt and read answer
        Console.WriteLine("Enter a UserID (Alphanumeric; no special characters): ");
        string userId = Console.ReadLine();
        
        // If the id is valid, return it and leave the method (ending the loop)
        if (ValidUserId(userId))
        {
            return userId;
        }
        
        // If we got here, then the id is invalid and we should inform the user to try again
        Console.WriteLine("Userid can only contain A-Z, a-z & 0-9. Try again");
    }
}
现在在main方法中,我们可以在需要获取用户ID时引用此方法。检查用户是否已经存在的循环现在可以单独实现以读取用户输入,因此不再需要考虑两种不同的情况:

public void CreateAccount()
{
    Console.WriteLine("----- Create New Account -----\n" +
        "Enter following account information:\n");

    string userId = null;
    bool isNewUser = false;
    while (!isNewUser)
    {       
        // Use our other method to read the user id
        userId = ReadUserId();
    
        if (data.IsUserInFile(userId))
        {
            Console.WriteLine("Userid already exists. Try again");
            continue;
        }
        
        isNewUser = true;
    }
}

一般来说,使用转到的最佳方法是不转到。但是你尝试过循环吗?当循环已经足够,并且让你的意图更加清晰时,你为什么要在这里使用
goto
?@jason.kaisersmith:“使用goto语句的唯一正确方法是不使用goto语句!”——你也碰巧错了。我同意大多数分支不应该使用
goto
。但它在
switch
语句中很重要,因为这是让一个
案例
落入另一个案例的唯一方法。@PeterDuniho。我同意为什么这个问题是封闭的。我还认为,最好提出一些问题,征求意见和其他方法来实现工作代码。@Flydog57即使是伟大的Dijkstra也承认,
goto
有其用途(也许这里没有!),例如,它经常被用于紧循环算法中,以打破内部循环,并重新排序分支。请参见,我将尝试这种方法。我唯一担心的是,由于我会对其他字段采用类似的方法,代码可能会变得混乱。@ManaswiPatil将内容划分为逻辑命名的方法肯定会有助于减少代码的混乱。我知道,似乎更多的分布式代码会使它更加混乱,但请考虑在第二个示例中阅读<代码> CurATACATEM()/<代码>方法。您可以看到
userId=ReadUserId()
并立即了解该方法将获得用户id等。因此,它使流程的实际核心更易于理解,然后如果需要查看各个位的作用,可以转到各个方法。还请注意,并非所有内容都需要在循环中。一旦任一示例的
CreateAccount
方法中的
while
循环完成,您可以根据需要使用已验证的
userId
。@ManaswiPatil为避免混淆,请确保使用单独的方法。也很有可能,您实际上可以将方法设置为泛型,并传入所需的详细信息,例如要检查的字段的名称。@Llama您的方法对我很有效。使用
continue
with
if
loop in
,同时
loop提供我所需的精确工作。谢谢