【问题标题】:Alternative to goto statementgoto 语句的替代方案
【发布时间】:2016-08-16 09:14:07
【问题描述】:

我是 C# 的新手(一周前开始学习),在批处理和表达式 2 方面有一点经验,我一直在开发基于文本的游戏以尝试了解更多信息。起初我使用 goto 语句,但根据我发现的几乎每个人的说法,goto 语句是死亡和绝望的混合物,所以我想学习更清洁、更少邪恶的方法来达到同样的效果。这是我为演示我的意思而制作的一个糟糕的示例脚本:

using System;

namespace TestScript
{
class Program
{
   public static void Main(string[] args)
    {
       string ConsoleReadinator;
        string ConsoleReadinator2;
        int Go = 0;

    mainmenu:
        do
        {
            Go = 0;
            Console.Clear();
            Console.WriteLine("Main Menu:");
            Console.WriteLine("Store or something");
            ConsoleReadinator = Console.ReadLine().ToUpper();
            if (ConsoleReadinator == "STORE") { Go = 1; }
        } while (Go == 0);

      // In-game store example

        {
            Go = 0;
            do
            {
                Console.Clear();
                Console.WriteLine("In-game store I guess");
                Console.WriteLine("Stuff you can buy, etc");
                ConsoleReadinator2 = Console.ReadLine().ToUpper();
                if (ConsoleReadinator2 == "GO") { Go = 1; }
            } while (Go == 0);
            goto mainmenu;
        }
    }
  }
}

这个脚本是功能性的,但我想避免使用goto 作为返回先前语句以导航菜单并可能重复回合制游戏的算法的一种方式。我在Alternative to using goto statement in C# 中读到了有关为此使用方法的信息(这基本上与我的问题相同,只是有点模糊),但是 Greg 在那里制作的示例对我根本不起作用,以至于它可能不是值得尝试使该特定示例起作用。

【问题讨论】:

  • 我认为更适合这个问题的网站是codereview.stackexchange.com
  • 是的,永远不要使用 goto 语句
  • @Liam 这篇文章的重点是永远不要使用 goto 语句。
  • 我可能会被激怒,但是经过大约 20 年的开发 - DOS、Windows、C++、ASP、C# 等。我认为在方法中使用 goto 是一种简单的好方法处理复杂代码中的错误。我对面的数字,C++ 高级工程师和可怕的聪明,同意。

标签: c# goto


【解决方案1】:

据我所知,你想要一个无限循环

  ...
  while (true) 
  {
      do
      {
         ...
      } while (Go == 0);

      Go = 0;

      do
      {
         ...
      } while (Go == 0);
  }

【讨论】:

  • 几分钟前我对此发表评论说它有效,并且在本示例中有效,但我忽略了将有多种选择;不仅仅是一家商店。如果我使用这样的无限循环,我想我将不得不循环浏览每个菜单,除非我使用了很多循环。
  • @Rowan Tarshis:为什么不添加另一个菜单项,Exit 只需调用break;(只留下上面的无限循环)或return;(到离开Main 函数和程序)?
  • 我不确定你的意思。 “另一个菜单项”是指另一个菜单,比如商店,还是其他什么?此外,"Exit on which just call break;(只留下上面的无限循环)"是指它将break; 进入第二个无限循环,还是我误解了?
  • @Rowan Tarshis: 是的,就像"Store",所以当用户打印时,说“退出”我们就离开循环
【解决方案2】:

您可以使用递归来返回并再次执行代码。为此,您可以将代码移至单独的方法并在此方法中调用它:

class Program
{
   public static void Main(string[] args)
   {
        string ConsoleReadinator;
        string ConsoleReadinator2;
        Method(0);
   }
 
   private static void Method(int Go)
   {    
        do
        {
            ..
        } while (Go == 0);

      // In-game store example

        do
        {
           ...
        } while (Go == 0);
        Method(Go);
   }
}

或者您可以以更好的方式使用循环。让我们看一下我们希望用户输入整数时的示例:

   public static void Main(string[] args)
   {
       int num;

       // This loop ends only when user enters proper integer number
       do
       {
          Console.Clear();
          Console.Write("Please enter some integer number: ");
       } while(!int.TryParse(Console.ReadLine(), out num));                      
   }

这可以通过递归来完成:

   public static int EnterNumber()
   {
       Console.Clear();
       Console.Write("Please enter some integer number: ");

       // if the number is successfully parsed return number else run this method again
       return int.TryParse(Console.ReadLine(), out num) ? num : EnterNumber();
   }

   public static void Main(string[] args)
   {
       int num = EnterNumber();
   }

有了我们拥有的所有选项(方法、循环和递归),已经没有使用 GO TOs 的实际用例了。

【讨论】:

    【解决方案3】:

    通常您使用方法或 lambda 表达式。因此,您的 mainmenu 将成为您在代码末尾再次调用的方法。

    【讨论】:

      【解决方案4】:

      一个建议是使用这样的 switch case 构造:

      static void Main(string[] args)
      {
          string ConsoleReadinator;
          string MENU_TEXT = "Main Menu:";
          string ADDITIONAL_INFO = "Store or something";
      
          bool endProg = false;
      
      
          ConsoleReadinator = printMenu(MENU_TEXT, ADDITIONAL_INFO);
      
          // as long "EXIT" is not typed
          while (!endProg)
          {
      
              switch (ConsoleReadinator)
              {
                  case "STORE":
                      // Do your Store Stuff
                      // maybe change MENU_TEXT and ADDITIONAL_INFO 
                      // and print a new Menu
                      ConsoleReadinator = printMenu(MENU_TEXT, ADDITIONAL_INFO);
                      break;
                  case "GO":
                      // Do your Go Stuff
                      break;
                  case "EXIT":
                      endProg = true;   // set exit condition to true
                      break;
      
                  default:                        
                      break;
              }
          }
      
          Console.ReadKey();
      }
      
      // one Method to use for Menu display
      public static string printMenu(string menuText, string additionalInfo)
      {
          Console.Clear();
          Console.WriteLine(menuText);
          Console.WriteLine(additionalInfo);
      
          return Console.ReadLine().ToUpper();
      
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2011-01-26
        • 2013-11-18
        • 1970-01-01
        • 2011-01-19
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多