我应该如何让我的 "goto" 最后不变成 运行?

How should I make my "goto" not to run at the end?

您好! :D 所以,我在下面有这段代码。它正在工作,但我不会说它按照我希望的方式工作。 所以,我使用 goto 跳转到代码的末尾。但是在 if 的最后阶段,我有一个 goto 导航到 igen: Console.WriteLine("Remek! Estre 8-ra érted megyek!");。当这种情况发生时,我不希望下面的代码( nem: Console.WriteLine("Kár, pedig szívesen elhívtalak volna randizni. :(");)变为运行。我怎样才能让它工作? 提前致谢!

using System.Reflection.Emit;

namespace Randi
{
    class Program
    {

        static void Main(string[] args)
        {
            Console.WriteLine("Hány centi vagy?");

            int cm = int.Parse(Console.ReadLine());
            if (cm <= 175 && cm >= 150);
            else goto nem;
            {
                Console.WriteLine("Naa, tök jó! Az alacsony lányok cukik.");
                Console.WriteLine("Hány éves vagy?");
                int év = int.Parse(Console.ReadLine());
                if (év <= 18 && év >= 16);
                else goto nem;
                {
                    Console.WriteLine("Akkor még korban is összepasszolunk!");
                    Console.WriteLine("Van barátod?");
                    
                    string kapcsolat = Console.ReadLine();
                    if (kapcsolat.Contains("Nincs"));
                    else goto nem;
                    {
                        Console.WriteLine("Örülök neki! Eljönnél velem randizni? (Igen/Nem)");

                        string randi = Console.ReadLine();
                        if (randi.Contains("Igen")) goto igen;
                        else goto nem;
                    } 
                        
                }
            
            }
        igen:
            Console.WriteLine("Remek! Estre 8-ra érted megyek!");
        nem:
            Console.WriteLine("Kár, pedig szívesen elhívtalak volna randizni. :(");

            Console.ReadKey();
        }

    }
}

您可以直接从 second-to-last 案例跳到最后:

// snip!
igen:
    Console.WriteLine("Remek! Estre 8-ra érted megyek!");
    goto end;
nem:
    Console.WriteLine("Kár, pedig szívesen elhívtalak volna randizni. :(");

end:
    Console.ReadKey();

然而,正如任何编码过的人都会指出的那样,使用 goto 进行复杂的控制流通常不是一个好主意,如果你有很好的理由的话。

你似乎有一些逻辑来决定两种可能结果之一,nemigen(我不懂你的语言,所以我不知道这段代码实际上做了什么,但是唉)基于用户交互。我们可以将决定结果的部分重构为一个方法,并将其与作用于该结果的代码分开:

static void Main()
{
    var outcome = Interact();

    if (outcome)
    {
        Console.WriteLine("Remek! Estre 8-ra érted megyek!");
    }
    else
    {
        Console.WriteLine("Kár, pedig szívesen elhívtalak volna randizni. :(");
    }

    Console.ReadKey();
}

static bool Interact()
{
    int cm = int.Parse(Console.ReadLine());
    if (cm <= 175 && cm >= 150);
    else return false;
    {
        Console.WriteLine("Naa, tök jó! Az alacsony lányok cukik.");
        Console.WriteLine("Hány éves vagy?");
        int év = int.Parse(Console.ReadLine());
        if (év <= 18 && év >= 16);
        else return false;
        {
            Console.WriteLine("Akkor még korban is összepasszolunk!");
            Console.WriteLine("Van barátod?");
            
            string kapcsolat = Console.ReadLine();
            if (kapcsolat.Contains("Nincs"));
            else return false;
            {
                Console.WriteLine("Örülök neki! Eljönnél velem randizni? (Igen/Nem)");

                string randi = Console.ReadLine();
                if (randi.Contains("Igen")) return true;
                else return false;
            }
        }
    }
}

我所做的只是将 goto nem 替换为 return false,将 goto igen 替换为 return true。这样好一点,但是跟踪这段代码的流程仍然很困难。首先,每个 if (cond); else return x 都是一个非常混乱的结构。说 if (!cond) return x; 是等效的,更容易理解。另外,您使用的是代码块,但它们没有引入任何有用的结构,只会增加嵌套并使其更难理解。我们可以去掉所有额外的大括号和制表符。 Interact 现在变成:

static bool Interact()
{
    int cm = int.Parse(Console.ReadLine());

    if (cm > 175 || cm < 150)
    {
        return false;
    }

    Console.WriteLine("Naa, tök jó! Az alacsony lányok cukik.");
    Console.WriteLine("Hány éves vagy?");

    int év = int.Parse(Console.ReadLine());

    if (év > 18 || év < 16)
    {
        return false;
    }
    
    Console.WriteLine("Akkor még korban is összepasszolunk!");
    Console.WriteLine("Van barátod?");

    string kapcsolat = Console.ReadLine();

    if (!kapcsolat.Contains("Nincs"))
    {
        return false;
    }

    Console.WriteLine("Örülök neki! Eljönnél velem randizni? (Igen/Nem)");

    string randi = Console.ReadLine();
    
    if (!randi.Contains("Igen"))
    {
        return false;
    }

    return true;
}

这看起来更好。至少现在你可以自上而下地阅读这个方法,很容易看出我们所做的是读取用户输入 3 次,检查该输入的一些条件并确定它是否有效。

我想说这对于你的玩具示例来说已经足够了,但是在这个过程之后,更多的重构机会出现了——这个方法有效地处理了 3 个独立的条件,所以也许每个验证步骤的 3 个独立的方法会使代码更可读?通过删除 gotos,您可以更好地控制代码的结构,而结构是可读性的关键。老实说,您的原始代码段中的嵌套级别和 goto 仅仅看着它们就让我感到非常疲倦。您很快就会发现使用此类代码很麻烦,并且您不希望编程成为麻烦。

不要使用 goto 语句,而是使用函数。它可能会导致意大利面条代码并使其难以维护。另请参阅 Go To Statement Considered Harmful。只有少数情况(错误处理、状态机)goto 可以产生更清晰的代码。大多数情况下,您会发现有比使用 goto 更好的解决方案。如果您发现自己需要使用 goto,您应该确保它是唯一的选择。