关于c#:交换机中的一个案例怎么可能没有休息?

How can a case in a switch not have a break?

本问题已经有最佳答案,请猛点这里访问。

我最近继承了一些写得很差的代码。不幸的是,这是一个我们高度依赖的系统,而且没有时间重新编写它,所以我一直在维护它,并在继续编写时重新编写片段。然而,今天我偶然发现了这个包含开关的方法,其中一个case语句没有中断。这是如何编译的?据我所知,所有案件都必须破译、归还或转移。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
private void ReadBadge_Activated(object sender, EventArgs e)
    {
        try
        {
            if (!bInHideMode)
            {
                // Set Button states
                btnCancelSwipe.Visible = true;
                btnCancelSwipe.Refresh();

                // Enable the Timeout timer
                //tmrTimeout.Enabled = true;

                // Refresh data
                switch (mManageAction)
                {
                    case"LogOnManager":
                    case"NormalUse":
                        lblSwipeStatus.Text ="Pass ID Badge
Near The Reader"
;
                        break;
                    case"AddNewUser":
                        lblSwipeStatus.Text ="Pass ID Badge
Near The Reader
For:"
+ mUserName;
                        break;
                    default:
                        lblSwipeStatus.Text ="Pass ID Badge
Near The Reader
For:"
+ mUserName;
                        break;
                }
            }
        }
        catch (Exception ex)
        {
            MessageBoxNoClick.MessageBox2(ex.Message,"Error Message");
        }
    }


这种结构:

1
2
3
4
5
case"LogOnManager":
case"NormalUse":
    lblSwipeStatus.Text ="Pass ID Badge
Near The Reader"
;
    break;

基本上意味着第二个case中的代码将用于任意一个case。所以这两种情况都使用相同的代码。

从语义上来说,这可以被认为是:

1
2
3
4
case"LogOnManager" ||"NormalUse":
    lblSwipeStatus.Text ="Pass ID Badge
Near The Reader"
;
    break;

但这并不能编译为该switch语句的有效条件。(如果你想真正获得技术,可能有两个原因,但主要是因为这是对boolswitch的评估是在string上运行的)所以你找到的版本可以代替它。

当省略break语句时(或者更具体地说,当case块为空时),无论下一个case是什么值,过程都将继续进行。


如果一个开关盒没有断开,那么它将通过下一个开关盒。请注意,在c中,只有当案例主体中没有任何内容时,它才起作用。

从文档中:

C# does not support an implicit fall through from one case label to another. The one exception is if a case statement has no code.


在这种情况下,没有中断的情况只意味着它将和它下面的情况一样。

因此,这些案例中的任何一个都会做同样的事情:

1
2
3
4
5
  case"LogOnManager":
  case"NormalUse":
                    lblSwipeStatus.Text ="Pass ID Badge
Near The Reader"
;
                    break;

这叫做"摔倒"


正如其他人指出的,这是一个有效的失败案例。由于两个"case"语句之间没有代码行,因此两个语句将运行相同的代码行。

因此,这将导致一个错误:

1
2
3
4
5
6
7
8
9
10
11
switch (mManageAction)
{
    case"LogOnManager":
         lblSwipeStatus.Text ="Pass ID Badge
Near The Reader"
;
         // Hey! Add a break here. ERROR
    case"NormalUse":
        lblSwipeStatus.Text ="Pass ID Badge
Near The Reader"
;
        break;
}

参考https://msdn.microsoft.com/en-us/library/06tc147t.aspx


只有breakreturngotothrow等)没有明确的结尾,才是case"LogOnManager":。它没有主体,但与随后的案例相同。这是允许的,允许多个大小写标签共享一个块。

长期以来,人们一直认为避免摔倒是最好的做法,但像这样的情况被认为是可以的,因为仍然只有一具尸体。当C禁止隐式摔倒(要求Goto明确表示)是由于这种观点,只有这样的例子才是好的实践。因此,这种类型并没有被禁止。


根据C规范:

8.7.2 If the end point of the statement list of a switch section is reachable, a compile-time error occurs. This is known as the"no fall
through" rule.

在您的例子中,由于LogOnManagerNormalUse都将执行第一个表达式,因此无法到达终点。


这意味着对同一段代码应用两个标签。这是一个有效的案例。

以下是官方文件:

A switch statement can include any number of switch sections, and each section can have one or more case labels (as shown in the string case labels example below). However, no two case labels may contain the same constant value.


如果case语句没有中断,将执行下一个case中的traitement