在交换机中使用'转到'?

时间:2011-01-21 06:37:42

标签: c# coding-style switch-statement goto

我看过一个建议的编码标准,内容为Never use goto unless in a switch statement fall-through

我不跟随。这个“例外”案例究竟是什么样的,证明了goto

的合理性

7 个答案:

答案 0 :(得分:90)

此构造在C#中是非法的:

switch (variable) {
   case 2: 
       Console.WriteLine("variable is >= 2");
   case 1:
       Console.WriteLine("variable is >= 1");
}

在C ++中,如果variable = 2,它将运行两行。这可能是故意的,但是在第一个案例标签的末尾忘记break;太容易了。出于这个原因,他们在C#中将其定为非法。要模仿堕落行为,您必须明确使用goto来表达您的意图:

switch (variable) {
   case 2: 
       Console.WriteLine("variable is >= 2");
       goto case 1;
   case 1:
       Console.WriteLine("variable is >= 1");
       break;
}

也就是说a few cases其中goto实际上是解决问题的好方法。 Never shut down your brain“永不使用”规则。如果它是100%无用的,那么首先它不会存在于语言中。不要使用goto指南;这不是法律。

答案 1 :(得分:21)

C#拒绝让案件隐含地落入(除非案例中没有代码),如C ++:你需要来包含break。要明确通过(或跳转到任何其他情况),您可以使用goto case。由于没有其他方法可以获得这种行为,大多数(合理的)编码标准都会允许它。

switch(variable)
{
case 1:
case 2:
    // do something for 1 and 2
    goto case 3;
case 3:
case 4:
    // do something for 1, 2, 3 and 4
    break;
}

一个现实的例子(按要求):

switch(typeOfPathName)
{
case "relative":
    pathName = Path.Combine(currentPath, pathName);
    goto case "absolute";

case "expand":
    pathName = Environment.ExpandEnvironmentVariables(pathName);
    goto case "absolute";

case "absolute":
    using (var file = new FileStream(pathName))
    { ... }
    break;

case "registry":
    ...
    break;
}

答案 2 :(得分:7)

   public enum ExitAction {
        Cancel,
        LogAndExit,
        Exit
    }

这更整洁

ExitAction action = ExitAction.LogAndExit;
switch (action) {
    case ExitAction.Cancel:
        break;
    case ExitAction.LogAndExit:
        Log("Exiting");
        goto case ExitAction.Exit;
    case ExitAction.Exit:
        Quit();
        break;
}

比这更好(特别是如果你在Quit()中做更多的工作)

ExitAction action = ExitAction.LogAndExit;
switch (action) {
    case ExitAction.Cancel:
        break;
    case ExitAction.LogAndExit:
        Log("Exiting");
        Quit();
        break;
    case ExitAction.Exit:
        Quit();
        break;
}

答案 3 :(得分:4)

这是C#允许切换案例“漏洞”的唯一方法。在C#中(与C,C ++或Java不同),switch语句中的case块必须以break或其他显式跳转语句结束。

答案 4 :(得分:4)

除了使用goto case之外,您还可以goto另一个案例中的标签:

    switch(i) {
    case "0":
        // do some stuff
        break;
    case "1":
        // other stuff, then "fall through" to next case clause
        goto Case2;
    case "2":
    Case2:
        break;
    }

这样,您可以跳转到另一个case子句而不必担心表达式的值或类型。

可以替代break的某种明确的“fallthrough”关键字本来不错,不过......

答案 5 :(得分:1)

通过对Mehrdad Afshari上述建议的延伸,我绝不会提倡简单地将一个结构放逐为“坏代码”或“错误的编码实践”。甚至'goto'陈述也在宏观计划中占有一席之地。由于构造中存在任何固有的缺陷,它们是邪恶的教条并没有成功 - 这是因为它们被大量(并且很差)过度使用。

无论如何,Kernighan和Ritchie觉得允许案件落空是正确的方法。坦率地说,我更倾向于相信他们的推理,而不是整个华盛顿州雷蒙德市的任何想法。或任何基于雷德蒙德任何思想智慧的教条。

如果您听过“从不使用xxx”,请在心理上附加“无原因”。只是粗暴地抛出任何东西都是荒谬的。存在设备是因为有理由制作它们。事后看来,它们通常被称为“坏”,不是因为设备本身有任何缺陷,而是因为那些没有完全理解它们的人使用它们很差。因此,该设备几乎不会“坏”。用户理解几乎总是坏的。即使是原子裂变和融合也是如此。

我看到了可怕的怪诞代码结构,其唯一的功能是避免使用'goto'语句。更糟的是什么? “goto [label]”,或30行令人作呕的代码,其功能是避免输入“goto [label]”?

在教条之前寻求知识。三思而后行。这些是有用的建议。

答案 6 :(得分:0)

我知道这是旧话题,但问题仍然存在。我们可以在goto语句中使用下一个代码而不是丑陋的版本吗?

var variable = 2;
switch (variable)
{
case 2:
Console.WriteLine("variable is >= 2");
goto case 1;
case 1:
Console.WriteLine("variable is >= 1");
break;


}

可以用下一个更整洁的代码代替:

if (variable >= 2)
{
Console.WriteLine("variable is >= 2");
}
if (variable >= 1)
{
Console.WriteLine("variable is >= 1");
}