Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/294.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 转到被认为有害的声明?_C#_.net_Goto_Base Class Library - Fatal编程技术网

C# 转到被认为有害的声明?

C# 转到被认为有害的声明?,c#,.net,goto,base-class-library,C#,.net,Goto,Base Class Library,如果上面的陈述是正确的,那么为什么我在.Net BCL上使用reflector时会看到它被大量使用 编辑:让我换一句话:我在reflector中看到的所有GO-TO都是由人类或编译器编写的吗?这些goto通常是由编译器生成的,尤其是在枚举器内部。 编译器总是知道她在做什么 如果您发现自己需要使用goto,您应该确保它是唯一的选项。通常你会发现有更好的解决方案 除此之外,很少有实例可以证明使用goto是合理的,例如使用嵌套循环时。同样,在这种情况下,还有其他选择。您可以在函数中中断内部循环并使用r

如果上面的陈述是正确的,那么为什么我在.Net BCL上使用reflector时会看到它被大量使用


编辑:让我换一句话:我在reflector中看到的所有GO-TO都是由人类或编译器编写的吗?

这些
goto
通常是由编译器生成的,尤其是在枚举器内部。
编译器总是知道她在做什么

如果您发现自己需要使用
goto
,您应该确保它是唯一的选项。通常你会发现有更好的解决方案

除此之外,很少有实例可以证明使用
goto
是合理的,例如使用嵌套循环时。同样,在这种情况下,还有其他选择。您可以在函数中中断内部循环并使用return语句。如果额外的方法调用成本太高,则需要仔细查看


回应您的编辑:


不,不是所有的GOTO都是由编译器生成的,但它们中的很多都是由编译器生成的状态机(枚举器)、switch case语句或优化的if-else结构生成的。只有少数几个实例可以判断它是编译器还是原始开发人员。通过查看函数/类名可以得到一个很好的提示,编译器将生成“禁止”的名称,以避免名称与代码冲突。如果一切正常,代码没有经过优化或模糊处理,那么goto的使用可能是有意的

转到
语句本身并不有害,有时甚至非常有用。有害的是那些倾向于在代码中把它放在不合适的地方的用户。

以上所述并不完全正确-这是在gotos几乎是唯一使用的流量控制结构的时候。事实上,有几个人对此提出了反驳,包括Knuth的经典“使用Goto的结构化编程”论文(来自内存的标题)。在某些情况下(错误处理、状态机),GOTO可以生成比“结构化”替代方案更清晰的代码(IMHO)。

当编译为汇编代码时,所有控件都是结构化的,并转换为(非)条件跳转。然而,优化器可能太强大,当反汇编程序无法识别跳转模式对应的控制结构时,总是正确的语句,即
goto标签将被发出


这与“goto”的危害(无危害性)无关,我认为以下摘录与此特别相关:

可能是最著名的批评 GOTO是Edsger在1968年写的一封信 Dijkstra打电话给Go-To声明 被认为是有害的。在那封信里 Dijkstra认为无限制的GOTO 声明应从 高级语言,因为它们 使分析和分析的任务复杂化 验证程序的正确性 (特别是涉及回路的回路)。 提出了另一种观点 在Donald Knuth的结构化 使用go to语句编程 它分析了许多常见的编程 任务,并在其中一些任务中发现 GOTO是最佳的语言结构 使用

因此,一方面,我们(一位才华横溢的计算机科学家)反对使用
GOTO
语句,特别是反对过度使用
GOTO
语句,理由是它是一种结构更少的代码编写方式

另一方面,我们(另一位才华横溢的计算机科学家)认为,使用
GOTO
,尤其是明智地使用它,实际上可能是给定程序代码的“最佳”和最佳结构

最后,我相信这两个人都是对的。Dijkstra是正确的,因为过度使用
GOTO
语句肯定会使一段代码的可读性和结构化程度降低,从纯理论的角度来看计算机编程时,这是正确的

然而,Knuth也是正确的,因为在“现实世界”中,一个人必须采取务实的方法,如果使用得当,
GOTO
语句确实是语言结构的最佳选择

goto
被认为是有害的(供人类使用,但 对电脑来说没关系)

因为无论我们(人类)如何疯狂地使用
goto
,编译器总是知道如何读取代码

相信我

阅读带有
goto
s的其他代码很难。
阅读带有
goto
s的您自己的代码更难


这就是为什么在低级(机器语言)中使用它,而不是在高级(人类语言,例如C#、Python……)中使用它的原因

一般规则是不需要使用
goto
。与任何规则一样,当然也有例外,但与任何例外一样,例外很少

goto
命令就像毒品一样。如果只在特殊情况下使用有限的量,那就好了。如果你总是用得太多,它会毁了你的生活


当您使用Reflector查看代码时,您并没有看到实际的代码。您看到的代码是根据编译器从原始代码生成的内容重新创建的。当您在重新创建的代码中看到
goto
时,无法确定原始代码中是否存在
goto
。可能有一个更结构化的命令来控制流,比如
break
continue
,编译器以与
goto
相同的方式实现了该命令,因此,Reflector无法区分两者之间的区别。

请记住,您在Reflector中看到的代码是一个反汇编程序——Reflector正在查看已编译的字节码,并试图拼凑原始源代码

因此,您必须记住,禁止
goto
s的规则适用于高级代码。用于替换
goto
s(
for
)的所有构造
A:
    if !(a > b)
        goto B;
    DoStuff();
    goto A;
B:  ...
 while (a > b)
    DoStuff();
static void DoAction(params int[] args)
{
  foreach (int arg in args)
  {
    Console.WriteLine(arg);
    if (arg == 93) goto exit;
  }

  //edit:
  if (args.Length > 3) goto exit;
  //Do another gazillion actions you might wanna skip.

  //etc.
  //etc.

exit:
  Console.Write("Delete resource or whatever");
}
 foreach (KeyValuePair<DateTime, ChangedValues> changedValForDate in _changedValForDates)
            {
                foreach (KeyValuePair<string, int> TypVal in changedValForDate.Value.TypeVales)
                {
                    RefreshProgress("Daten werden geändert...", count++, false);

                    if (IsProgressCanceled)
                    {
                        goto TheEnd; //I like goto :)
                    }
                }
            }
TheEnd:
  foreach(KeyValuePair<DateTime, ChangedValues> changedValForDate in _changedValForDates)
    {
                    foreach (KeyValuePair<string, int> TypVal in changedValForDate.Value.TypeVales)
                    {
                        RefreshProgress("Daten werden geändert...", count++, false);

                        if (IsProgressCanceled)
                        {
                            break; //I miss goto :|
                        }
                    }

                 if (IsProgressCanceled)
                 {
                            break; //I really miss goto now :|
                 }//waaaAA !! so many brakets, I hate'm
    }