【问题标题】:goto difficulties with C#解决 C# 的困难
【发布时间】:2012-09-30 22:05:11
【问题描述】:

为什么会出现以下编译错误:

//错误CS0159:没有这样的标签'lbl_proc_20'

使用以下代码:

//JUST A DUMMY CODE TO ILLUSTRATE THE CONCEPT
int a = resultOfFunction1();
int b = resultOfFunction2();

//10+ Local variables that are calculated depending on the results above

if (a < 10)
{
    switch (b)
    {
        case 0:
            //Actions for A<10, B=0, using local variables
            break;
        case 1:
            double c = someFunction(a, b);  //In real code involves calculations based on a and b
            if(c > 10.0)
                goto lbl_proc_20;   //error CS0159: No such label 'lbl_proc_20' within the scope of the goto statement

                    //Actions for A<10, B=1, using local variables
            break;
        default:
            //Actions for A<10, B=Other, using local variables
            break;
    }
}
else if (a < 20)
{
lbl_proc_20:
    switch(b)
    {
        case 0:
            //Actions for A<20, B=0, using local variables
            break;
        case 1:
            //Actions for A<20, B=1, using local variables
            break;
        case 2:
            //Actions for A<20, B=2, using local variables
            break;
        default:
            //Actions for A<20, B=Other, using local variables
            break;
    }
}
else if (a < 30)
{
    switch(b)
    {
        case 0:
            //Actions for A<30, B=0, using local variables
            break;
        case 1:
            //Actions for A<30, B=1, using local variables
            break;
        case 2:
            //Actions for A<30, B=2, using local variables
            break;
        default:
            //Actions for A<30, B=Other, using local variables
            break;
    }
}

为什么我会收到 goto 语句错误以及如何使其工作?

编辑:更改了示例以说明实际代码。

【问题讨论】:

  • 'goto' 一定是编程界的新名词,哈哈 :D
  • @user843732 - 是的,超过 30 年。有充分的理由,而不仅仅是微软。
  • @user843732 我建议您重新编写代码。只有非常非常非常特殊的情况可以选择 goto。

标签: c# goto


【解决方案1】:

您只能使用goto 跳转到goto 范围内的标签。来自描述错误CS0159docs

goto 语句引用的标签在 goto 语句的范围内找不到。

虽然标签存在,但你不能跳出if 块进入else 块。 else 中的代码与包含goto 的代码范围不同。

是时候重组你的代码了,这样就不需要goto了。

编辑

你应该尽量简化你的逻辑。多个函数优于goto 语句。

您可能要考虑的一个选项是Windows Workflow Foundation。这是一个非常简洁的工具,可让您以流程图的形式直观地表示您的逻辑。然后 WWF 将生成处理您指定的逻辑所需的代码。这可能会起作用,因为看起来您正在创建某种类型的有限状态机或类似过程。

【讨论】:

  • 你想告诉我你将如何重组它而不把它变成一个 10 功能的怪物吗?我发布的代码是我拥有的实际代码的图表。 PS。请注意,每个“switch”语句都有 3 到 4 个“case”,而实际代码中大约有 10 个外部“if”。
  • @user843732:不知道你的代码实际上应该做什么。
  • @user843732:好的,我添加了另一个选项。查看Windows Workflow Foundation
  • 谢谢。但是来一个,不要使用“goto”:)))))))
  • 这不仅仅是 goto。您提到的多个switchesifs 将使代码无法管理。另一方面,WWF 允许您在一个友好的拖放界面中设计您的逻辑。不要放弃 - 试试 WWF! :)
【解决方案2】:

作为对“如何在没有 goto 的情况下进行操作”的回应

bool pretendA20 = false;

if (a < 10)
{
    switch (b)
    {
        case 0:
            //Actions for A<10, B=0, using local variables
            break;
        case 1:
            double c = someFunction(a, b);  //In real code involves calculations based on a and b
            if(c > 10.0)
            {
                //goto lbl_proc_20;   
                pretendA20 = true;
                break;
             }

             //Actions for A<10, B=1, using local variables

            break;
        default:
            //Actions for A<10, B=Other, using local variables
            break;
    }
}

if ((a >= 10 && a < 20) || pretendA20)
{
//lbl_proc_20:
    switch(b)
    {

【讨论】:

  • 你所有的 'if's、'and's 和 'pretend's 将使我的实际代码完全不可读。但是,我想,你会坚持你的意见,我会坚持我的......到目前为止,我还没有听到任何关于“goto”为什么不好的争论。我知道 MS C# 编译器无法使用“goto”检查变量范围,但这并不能证明“goto”的“坏处”。这只是意味着 MS 无法制造出好的产品。这整个线程只是一个大名鼎鼎的称呼,并试图使我提出的代码“更难读”......
【解决方案3】:

C# 语言规范(第 8 章,第 249 页)指出:

如果当前函数中不存在具有给定名称的标签 成员,或者如果 goto 语句不在标签范围内, 发生编译时错误。该规则允许使用 goto 语句将控制转移出嵌套范围,但不转移到 嵌套范围。

在您的情况下,标签 lbl_proc_20goto 不在同一范围内,并且您正在尝试将控制权转移到另一个嵌套范围内。

您可以从这里获取语言规范:

http://www.microsoft.com/en-us/download/details.aspx?id=7029

【讨论】:

  • 好的,谢谢。我明白了。我想,我想问的是,如何以最少的参与来重写这个,因为微软似乎认为“goto”是不好的(这里的每个人都把它当作福音)?
  • @Kev 问题的标题并不总是清楚地代表其完整上下文的内容。这个问题与如何优化 .NET 的 IL 代码有关,要么像我的解决方案那样编写更好的代码,要么使用字节码优化器。问题的“问题”不是购物,而是找到解决我关于 IL 代码的技术问题的方法。问题不一定完全等同于问题。 Stackoverflow 是关于解决问题的。对不起,我选择了错误的措辞,我理解你的立场,但基于先入为主的看法。我为反刍俚语道歉。
  • @zezba9000 - 已接受道歉。我建议在Meta Stack Overflow 上询问这个问题,而不是在这里的 cmets 中讨论。谢谢。
猜你喜欢
  • 1970-01-01
  • 2020-10-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多