6

我知道使用 goto 是大多数人说要避免的事情,但是我在很多地方读到过,如果你需要简单的代码,有时它很有用。目前,如果用户选择,我有一个非常简单的程序需要重复:

static void Main()
{
    Restart:
    ...

    string UserChoice=Console.ReadLine();
    if (UserChoice=="y")
    goto Restart;
}

在这里使用 goto 真的很糟糕吗?我只是看不到任何其他方式如何在不执行循环等的情况下重复代码。这似乎是一种非常简单明了的方式。还是我错过了什么?

4

11 回答 11

20
string userchoice;

do {                

    userchoice=Console.ReadLine();

} while (userchoice=="y");
于 2010-09-24T09:14:21.903 回答
5

而是写下类似下面的内容。

while(Console.ReadLine() == "y")
{
.....
}

是的,使用 goto 很糟糕,因为它会降低您的代码的可读性。

于 2010-09-24T09:04:57.913 回答
5

当然,如果你的代码要一次又一次地做同样的事情,你必须添加一个循环。这比 goto 好多了。

使用这样的东西

string UserChoice = "y";
while( UserChoice == "y"){
  ...
  UserChoice=Console.ReadLine();
}

这对你应该很有效。

于 2010-09-24T09:05:21.267 回答
4

在这里使用 goto 真的很糟糕吗?

1968 年 3 月,Dijkstra向ACM 通讯部发送了一封信,该信函以Go To Statement Considered Harmful为标题发表。这是一本有趣的读物,也是程序员知识的一部分。

这封信中提出的反对 GOTO 的论点与程序员如何建立一个心智模型来跟踪代码执行的进度有关。Dijkstra 认为这种心智模型很重要,因为变量的值仅相对于执行进度才有意义。例如,当我们的程序计算一个事件发生的次数时,总会有一个中间时刻发生了 N 个事件,但跟踪它的变量还没有增加,仍然是 N-1。

他在反对 GOTO 的推理中经历了这些步骤:

  1. 首先考虑一种非常简单的语言,没有过程、循环或 GOTO。在这样的语言中,程序员可以通过想象一个从文件开头到结尾的执行指针来在心理上跟踪执行。单个索引(即行号)足以对执行进度进行建模。

  2. 现在我们将程序添加到语言中。执行进度不能再由单个索引跟踪,因为它可能在一个过程中。我们还必须跟踪该过程是从哪一行调用的。此外,可以从其他过程调用过程。因此,我们将执行进度建模为一系列索引。(在现实生活中,程序员将这样的序列称为“堆栈跟踪”。)

  3. 现在我们为语言添加循环。对于循环体中的堆栈跟踪中的每一行,我们需要添加另一种类型的索引来模拟执行进度:重复计数。

  4. 现在我们添加 GOTO。Dijkstra 认为,如果肆无忌惮地使用 GOTO,我们现在跟踪执行进度的能力就会崩溃。我们仍然可以通过说“现在我们正在执行第 152 条语句”来使用“执行时钟”跟踪执行进度。但是,这对于建立解释变量值所必需的上下文并没有真正的帮助。

只要我们只使用 GOTO 语句来构建简单的循环,你可以认为情况等同于第 (3) 点,没有问题。但在这种情况下,您可以只使用循环结构。最好将 GOTO 排除在您的代码之外,这样您就不会陷入第 (4) 点中描述的情况。

于 2010-09-24T11:08:45.107 回答
3

我会使用 do/while 循环:

string UserChoice = "";
do {
    ...
    UserChoice=Console.ReadLine();
} while(UserChoice == "y");
于 2010-09-24T09:06:02.700 回答
2

答案中缺少一个基本解决方案,

while (true)
{
    ...
    if (other-stop-condition) break;     

    ...

    string UserChoice=Console.ReadLine();
    if (UserChoice != "y") break;
}

break语句被认为不如纯 while 结构化,但比(真正的)goto 结构化。它应该谨慎使用,但它的用途与other-stop-condition

在这里使用 goto 真的很糟糕吗?

不在这个简单的程序中。但是,如果您继续使用goto替换循环、if/then 等,您的代码将比避免使用goto.

于 2010-09-24T10:02:42.777 回答
1

您可以使用递归函数在没有循环的情况下执行相同的操作:

public static void Main(string[] args)
{
   PrintChoices();
}

private static void PrintChoices()
{
    string userChoice = Console.ReadLine();

    if (userChoice == "y")
        PrintChoices();        
}
于 2010-09-24T09:07:24.460 回答
1

使用方法而不是 GOTO 被更广泛地接受:

static void Main()
{
    Restart();
}

static void Restart()
{
    ...code

    string userChoice = Console.ReadLine();
    if (userChoice=="y")
        Restart();
}
于 2010-09-24T09:09:36.017 回答
1

使用 do while 循环替换您的 goto,使其更具可读性。

do 
{
...
}
while(Console.ReadLine() == "y");
于 2010-09-24T09:13:48.583 回答
0

就我个人而言,我从来没有使用过 goto,就像 Øyvind Bråthen 和 Numenor 一样,循环方法是迄今为止完成这项任务的最佳方式。

但是,在一种情况下,我可以想到 goto 会有帮助的地方

在 C# 中,“fall through”开关是非法的(导致编译器错误):

switch (a) 
{ 
    case 3: 
        b = 7; 
    case 4: 
        c = 3; 
        break; 
    default: 
        b = 2; 
        c = 4; 
        break; 
}

要让它工作,你可以使用 goto:

switch (a) 
{ 
    case 3: 
        b = 7;
        goto case 4;
    case 4: 
        c = 3; 
        break; 
    default: 
        b = 2; 
        c = 4; 
        break; 
}
于 2010-09-24T09:12:01.203 回答
0
class Program
{
    static void Main(string[] args)
    {
        int add;
        try
        {
            ArrayList al = new ArrayList();
        t:
            Console.Write("Enter the Number of elements do you want to insert in arraylist");
            int n = Convert.ToInt32(Console.ReadLine());
            Console.WriteLine("Enter the Values:");
            for (int i = 0; i < n; i++)
            {
                al.Add(Console.ReadLine());

            }
            foreach (var a in al)
            {
                Console.WriteLine("valus:" + a);
            }
            Console.WriteLine("Add another number yes:1 ");
            add = Convert.ToInt32(Console.ReadLine());
            while (add == 1)
            {
                goto t;

            }
        }
        catch (Exception ex)
        {
            Console.WriteLine("Enter the Valid Number and try again");
        }
        Console.ReadKey();


    }
}

}

于 2018-03-11T09:23:03.543 回答