我看过一个建议的编码标准,内容为Never use goto unless in a switch statement fall-through
。
我不跟随。这个“例外”案例究竟是什么样的,证明了goto
?
答案 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");
}