【问题标题】:How goto statement works in this example?goto 语句在这个例子中是如何工作的?
【发布时间】:2010-08-31 16:46:16
【问题描述】:

我正在研究这个代码示例:

class Program
{
    static void Main(string[] args)
    {
        int x = 10;
        int y = 10;

        int generate=0;

        string [,] myArrayTable = new string[x, y];

        Console.WriteLine("Enter a seek number: ");
        string cautat = Console.ReadLine();

        for (int i = 0; i < x; i++)
        {
            for(int j = 0;j < y; j++)
            {
                myArrayTable[i, j] = (generate++).ToString();
            }
        }

        for(int i=0;i<x;i++)
        {
            for(int j=0;j<y;j++)
            {
                if(cautat.Equals(myArrayTable[i,j]))
                {
                    goto Found; 
                }
            }
        }

        goto NotFound;

        Found: 
          Console.WriteLine("Numarul a fost gasit");

        NotFound:
         Console.WriteLine("Numarul nu a fost gasit !");

        Console.ReadKey();
    }
}

如果我输入像 10 这样的搜索编号,我不明白为什么会调用“未找到”语句并且在控制台上打印相应的消息,在这种情况下 goto: Found 语句正在执行,所以 goto: NotFound 语句将永远不会调用,但其相应的消息仍然打印在控制台上,我不明白为什么在这种情况下程序永远不会跳转到这个“NotFound”标签。

如果你现在请帮我解决这个问题...

谢谢

【问题讨论】:

  • goto 误用的好例子
  • 你真的应该重组它,不要使用 goto 。这通常不被认为是好的做法,所以你会在代码审查中得到很多摇头,而且它往往是不可维护的。坦率地说,这会散发出明显的代码气味。

标签: c# goto


【解决方案1】:

Eww goto's,我会使用和if/else 声明,但如果你需要 goto's:

Found: 
  Console.WriteLine("Numarul a fost gasit");
  goto End;
NotFound:
  Console.WriteLine("Numarul nu a fost gasit !");
End:
Console.ReadKey();

【讨论】:

    【解决方案2】:

    我会重写这段代码以避免使用 goto:

    string message;
    if (myArrayTable.Cast<string>().Contains(cautat)) {
        message = "Found";
    } else {
        message = "Not found!";
    }
    Console.WriteLine(message);
    

    【讨论】:

      【解决方案3】:

      之所以调用它,是因为您在 Found 标签内的代码没有任何东西可以强制它跳过 NotFound 标签内的代码(除非您再次调用 goto,否则执行将通过标签而不是跳过它)。

      话虽如此,不要使用goto我会说它总是是个坏主意,可以重写。

      在您的情况下,您可以添加一个简单的布尔标志来摆脱您的 goto:

      static void Main(string[] args)
      {
          int x = 10, y = 10;
          bool isFound = false;
      
          // Rest of the body
      
          for(int i=0;i<x;i++)
          {
              for(int j=0;j<y;j++)
              {
                  if(cautat.Equals(myArrayTable[i,j]))
                  {
                      isFound = true;
                      break;
                  }
              }
      
              if(isFound)
                  break;
          }
      
          if(isFound)
              Console.WriteLine("Numarul a fost gasit");
          else
              Console.WriteLine("Numarul nu a fost gasit!");
      
          Console.ReadKey();
      }
      

      【讨论】:

      • 此重写将始终搜索数组中的所有元素,即使该元素已被找到。您可以通过在 for 循环中添加测试或使用 Contains 来避免这种情况。
      • Gotos 被认为是其他方法过于复杂和草率的状态返回代码的可行替代方案。当然,在这种情况下,goto 比使用布尔值退出循环要好。
      • @Mark Byers - 你是对的。我只是在删除 Goto 问题。我更新了我的示例,以便在找到某些内容后立即跳出循环(我会包含 Contains 示例,但 OP 从未说过他能够使用 Contains ...并且您已经处理了那个)。
      • @Nokikov,在这种情况下,我当然不会认为goto 是一个可行的选择。如果您不想使用布尔值退出循环,总有 Mark 的方法或将其设为函数并提前返回的替代解决方案。
      • “话虽如此,不要使用 goto!我会说它总是一个坏主意,可以重写。” - 如果这是你的意见,我没有问题(我同意诺维科夫)。但是你说它好像是编程的 10 条诫命,而我,反过来,强烈不同意。我也发现很少需要 goto,但我认为如果正确使用,特别是简单地打破嵌套循环(到单个标签,而不是本示例中的 2 个标签),它可能是最优雅的,更不用说最简单的解决方案了.
      【解决方案4】:

      因为您只是跳转到 Found 标签并继续下落到 Not Found 标签。您需要名为 EndFound 的第三个标签,并在找到后转到它。

      Found: 
          Console.WriteLine("Numarul a fost gasit");
          goto EndFound;
      NotFound:
          Console.WriteLine("Numarul nu a fost gasit !");
      EndFound:
      

      【讨论】:

        【解决方案5】:

        如果您不想在“Found”语句执行时执行“Not Found”语句,请使用另一个 goto,以跳过 NotFound 部分。 goto 跳转到一个部分,但这并不意味着如果没有通过 goto 跳转到该部分,则该部分将不会被执行。请记住,代码以自上而下的方式执行,因此除非您以某种方式跳过一段代码,否则它将执行。

        示例:

        Found:  
            Console.WriteLine("Numarul a fost gasit"); 
        
        goto ReadKey;
        
        NotFound: 
            Console.WriteLine("Numarul nu a fost gasit !"); 
        
        ReadKey:
            Console.ReadKey(); 
        

        【讨论】:

          【解决方案6】:

          因为跳转到Found 后,执行只是继续到下一行,恰好是“未找到”控制台写入行。您需要添加另一个 goto 来跳过它(或者更好的是,重新设计它以完全避免 goto)

          正是这样的问题,应该避免goto。

          【讨论】:

            猜你喜欢
            • 2021-10-05
            • 2017-11-26
            • 2021-10-14
            • 2021-10-05
            • 1970-01-01
            • 2018-12-16
            • 1970-01-01
            • 2016-07-15
            • 1970-01-01
            相关资源
            最近更新 更多