【问题标题】:How should I make my "goto" not to run at the end?我应该如何让我的“goto”最后不运行?
【发布时间】:2020-09-18 13:00:01
【问题描述】:

你好! :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();
        }

    }
}

【问题讨论】:

  • 您通常应该避免在 C# 中使用 goto。一般来说,这是一种巨大的代码气味,并且可能有一种更好的方式来构建您的代码。
  • 取每个 goto 标签中的代码。把它放在一个方法中。像这样重构你的代码。删除无用的括号。检查 IF 的一致性。看看会发生什么……这不是魔术。它只是结构化编程与非结构化编程。 OOP 是下一个级别。
  • 这显然不是使用goto 的情况。有一些,但我在一两年内只需要一次。

标签: c# if-statement goto


【解决方案1】:

您可以从倒数第二个案例跳到最后:

// 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,您可以更好地控制代码的结构,而结构是可读性的关键。老实说,你原来的 sn-p 中的嵌套级别和gotos 让我光看它们就很累。您很快就会发现使用这样的代码是一件令人讨厌的事情,而且您不希望编程成为一件麻烦事。

【讨论】:

  • 非常感谢你,伙计!现在它可以工作了:D 我刚刚开始学习如何编码,所以这是我的第一个“项目”之一 :)
【解决方案2】:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-03-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多