3

I have recently inherited some code that is very poorly written. Unfortunately, it is a system that we depend on highly, and there isn't time to re-write it all, so I am stuck maintaining it and re-writing pieces as I go along. However, today I stumbled on this method that contains a switch and one of the case statements has no break. How is this able to compile? It is my understanding that all cases have to break, return or goto.

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\nNear The Reader";
                        break;
                    case "AddNewUser":
                        lblSwipeStatus.Text = "Pass ID Badge\nNear The Reader\nFor: " + mUserName;
                        break;
                    default:
                        lblSwipeStatus.Text = "Pass ID Badge\nNear The Reader\nFor: " + mUserName;
                        break;
                }
            }
        }
        catch (Exception ex)
        {
            MessageBoxNoClick.MessageBox2(ex.Message, "Error Message");
        }
    }
Marko Lombardi
  • 131
  • 3
  • 10

8 Answers8

10

This structure:

case "LogOnManager":
case "NormalUse":
    lblSwipeStatus.Text = "Pass ID Badge\nNear The Reader";
    break;

basically means that the code in the second case will be used for either case. So both of the cases use the same code.

Semantically this could be thought of as:

case "LogOnManager" || "NormalUse":
    lblSwipeStatus.Text = "Pass ID Badge\nNear The Reader";
    break;

Except that this doesn't compile as a valid condition for that switch statement. (Potentially for a couple of reasons if you want to get really technical, but primarily because this evaluates to a bool and the switch is operating on a string.) So the version you've found does the job instead.

When a break statement is omitted (or, more specifically, when a case block is empty), the process will continue to whatever the next case is, regardless of the value used for that next case.

David
  • 208,112
  • 36
  • 198
  • 279
4

If a switch case doesn't have a break, then it will fall through the next case. Note that in C#, it only works if there is nothing in the case body.

From the Documentation:

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.

ergonaut
  • 6,929
  • 1
  • 17
  • 47
2

A case without a break in this case just means that it will do the same as the case underneath it.

So either of these cases will do the same thing:

  case "LogOnManager":
  case "NormalUse":
                    lblSwipeStatus.Text = "Pass ID Badge\nNear The Reader";
                    break;

It's called fall through

Gaz Winter
  • 2,924
  • 2
  • 25
  • 47
1

According to the C# Spec:

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.

In your case the end point isn't reachable as both LogOnManager and NormalUse will execute the first expression

m.edmondson
  • 30,382
  • 27
  • 123
  • 206
1

The only case without some explicit end (break, return, goto, throw, etc.) is case "LogOnManager":. It doesn't have a body, but shares that of the subsequent case. This is permitted, allowing multiple case labels to share a block.

It has long been considered best-practice to avoid fall-through but cases like this are considered OK as there is still just one body. When C# banned implicit fall-through (requiring goto to make it explicit) it was due to this view that only examples like this are good practice. Therefore that type wasn't banned.

Jon Hanna
  • 110,372
  • 10
  • 146
  • 251
1

As others pointed out, this is a valid case of fall-through. As there are no lines of codes between the two 'case' statements, both will run the same line of code.

So, this will cause an error:

switch (mManageAction)
{
    case "LogOnManager":
         lblSwipeStatus.Text = "Pass ID Badge\nNear The Reader";
         // Hey! Add a break here. ERROR
    case "NormalUse":
        lblSwipeStatus.Text = "Pass ID Badge\nNear The Reader";
        break;
}

For reference https://msdn.microsoft.com/en-us/library/06tc147t.aspx

Vittorio Sozzi
  • 103
  • 1
  • 9
0

if the case statement has no break the traitement in the next case will be executed

0

This means that 2 labels are applied for the same piece of code. It's a valid case.

Here is official documentation which cover this:

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.

Valentine
  • 506
  • 6
  • 23