为什么需要在switch语句的最后一个标签后放置?

当然编译器知道它是switch语句的最后一个标签?

在你的开关的最终案例陈述之后rest一下是好的防御性编程 。 如果将来可能会在下面添加另一个案例陈述,则可以消除程序流程从上述案例中流失的风险。

这是因为在C ++中会发生以下情况:

 switch(a) { case 1: // do stuff case 2: // do other stuff } 

如果a是1,那么 – 根据C ++规则 – “做东西” “做其他东西”都会发生。 因此,进入C#的C ++程序员不会被绊倒(并且为了使代码更清晰),C#要求您明确指定是要break还是通过不同的标签。

现在,至于为什么你需要在最后一个区块break ,这是一个简单的一致性问题。 它还使重新分解更容易:如果你移动案例,你不会因为缺少break语句而突然出现错误。 此外,当您想要添加其他标签等时会发生什么。

一致性。 与使用大括号的对象实例化语句中的最后一个枚举定义或最后一个赋值之后能够使用逗号的原因相同。 最后一种情况可能并不总是最后一种情况。

它也使得特殊情况减少。

如果是这种情况,则学习,编写或阅读更容易。 虽然这增加了一致性的东西。

在C#switch语句中,您必须明确声明要中断或转到另一个案例或转到默认值。

在C和C ++中,switch语句没有中断标记。 让用户明确说出他们想要做什么在C#中很重要,以避免错误。 例如,很多用户从C ++来到C#。


关于最后一个案例陈述,特别是你要问的问题。 我可以想到3个很好的理由。

  1. 保持任何语言的一致性非常重要。
  2. 如果您稍后追加另一个案例,默认应该做什么怎么办?
  3. 为什么要打破默认? 为什么不转到? 这里含糊不清。

根据http://msdn.microsoft.com/en-us/library/06tc147t.aspx

你不能“通过”任何开关部分,包括最后一个。

可以通过以下任何方式避免掉头:break,goto或return。

实际上有一种情况你不需要rest

考虑以下代码:

 using System; public class Program { public static void DoStuff() { } public static void DoAnotherStuff() { } public static void Main() { switch(1) { case 1: DoStuff(); break; default: DoAnotherStuff(); } } } 

使用C#4.0编译器它只会给你一个很好的CS0162:无法访问的代码警告

看来,由于switch有一个常量表达式,编译器已经知道它将要执行的路径,然后只是忽略了dafault标签。

很酷的是,如果你将switch(1)更改为switch(2),它就不再编译,因为默认标签缺少它的中断。

编辑:从C#参考

C#中的要求是每个交换机部分的末尾,包括最后一个,都是不可达的。 尽管通常使用跳转语句满足此要求,但以下情况也是有效的,因为无法到达语句列表的末尾。

 case 4: while (true) Console.WriteLine("Endless looping. . . ."); 

这就解释了为什么默认不需要rest。 实际上,任何不可缓存的标签都不需要中断,也不需要返回或转到

使用switchbreak不是唯一的选择。 您还可以选择转到另一个案例,转到默认案例,转到另一个标签或返回。 也可以有多个具有单个实现主体的案例。 由于最多有五个选项,并且能够为一个实现提供多个案例,因此编译器无法简单地输入“正确”的答案。

你必须选择你想做的事情。 它确保编译器做正确的事情,使你的代码更清晰,并使得更难以做愚蠢的程序员事情,比如在“最后一个”之后添加另一个案例,并且忘记放入break / goto / return。

根据Eric Lippert的博客文章 (案例2),它允许您能够任意重新订购您的开关部分,而不会意外地引入重大变化:

它[编译器]要求每个交换机部分(包括最后一个交换机部分)都有一个无法到达的端点。 这条规则的目的,以及一般的无法通过规则,是我们希望您能够随意重新订购开关部分,而不会意外地引入重大变化。

如上所述,您可以使用default:,但也可以考虑使用null。 case null:需要rest一下;

case null:iEvaluatedToNothing(); 打破;

如果你想“瀑布”,你可以做这样的事情;

 switch (deliverMail) { case null: case "": case "Address0": deliverMail0(); goto case "1"; case "1": deliverMail1(); break; } 

您可以根据需要使用它,但在最后一次评估时需要一个。