【问题标题】:Is this a good use of goto statement? [closed]这是很好地使用 goto 语句吗? [关闭]
【发布时间】:2021-04-14 05:37:47
【问题描述】:

我正在编写一个简单的 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 等其他字段使用相同的方法,因此我想确保在扩展其使用之前以正确的方式执行此操作。

【问题讨论】:

  • 使用goto 的最佳方式通常是不使用。但是您是否尝试过循环?
  • 如果一个循环就足够了,你为什么还要在这里使用goto,让你的意图更加清晰?
  • @jason.kaisersmith:“使用 GoTo 语句的唯一正确方法是不使用 GoTo 语句!”——你也碰巧错了.我同意 goto 不应该用于大多数分支。但它在 switch 声明中是必不可少的,因为这是让 case 落入另一个 case 的唯一方法。
  • @PeterDuniho 。 . .我同意这个问题被关闭的原因。我还认为最好在Code Review Stack Exchange 上提出征求意见和实现工作代码的替代方法的问题。
  • @Flydog57 即使是伟大的 Dijkstra 也承认 goto 有用途(也许不是在这里!),例如它经常用于紧密循环的算法中以打破内部循环,并重新排序分支.另见stackoverflow.com/questions/46586/goto-still-considered-harmful

标签: c# goto


【解决方案1】:

一种简单的方法是使用 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 声明移出循环,因为您可能需要在循环之后使用它。

或者,您可能会进一步分解您的代码。读取 userId 的整个方法可以移出到它自己的方法中:

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方法中我们需要获取userId的时候可以引用这个方法。检查用户是否已经存在的循环现在可以单独实现以读取用户输入,因此不再需要担心两种不同的条件:

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;
    }
}

【讨论】:

  • 我会尝试这种方法。我唯一担心的是,因为我会在其他领域采用类似的方法,所以代码可能会令人困惑。
  • @ManaswiPatil 将事物分成逻辑命名的方法绝对有助于减少代码混乱。我知道似乎更多的分布式代码会使它更加混乱,但请考虑在我的第二个示例中阅读CreateAccount() 方法。你看到userId = ReadUserId();,马上就明白这个方法会获取一个用户id等,所以它让进程的实际核心更容易消化,然后如果你需要看个别位做什么你可以去个别方法。
  • 另请注意,并非所有内容都需要在循环中。在任一示例的CreateAccount 方法中的while 循环完成后,您可以根据需要使用经过验证的userId
  • @ManaswiPatil 为避免混淆,请确保使用单独的方法。您也很可能实际上可以将方法设为通用并传入您需要的详细信息,例如您要检查的字段的名称。
  • @Llama 你的方法对我很有效。在while 循环中使用continueif 循环可以提供我需要的确切工作。谢谢。
猜你喜欢
  • 1970-01-01
  • 2012-08-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多