182

I am trying to write a switch statement that would type the search term in the search field depending on whichever search textbox is present. I have the following code. But I am getting a "Control cannot fall through from one case label" error.

switch (searchType)
{
    case "SearchBooks":
        Selenium.Type("//*[@id='SearchBooks_TextInput']", searchText);
        Selenium.Click("//*[@id='SearchBooks_SearchBtn']");

    case "SearchAuthors":
        Selenium.Type("//*[@id='SearchAuthors_TextInput']", searchText);
        Selenium.Click("//*[@id='SearchAuthors_SearchBtn']");
}

Control cannot fall through from one case label (case "SearchBooks":) to another

Control cannot fall through from one case label (case "SearchAuthors":) to another

Community
  • 1
  • 1
Maya
  • 7,053
  • 11
  • 42
  • 53
  • I just realized how significantly nicer a switch statement would look if we didn't have to put `break;` in there. It's a horrible artifact from the past. – Simon_Weaver May 04 '21 at 19:08
  • @Simon_Weaver Sometime you do want to group several case items and treat them the same! Falling through is very nice in those cases. – stackoverblown Aug 08 '21 at 12:02
  • @stackoverblown definitely, but that's sort of a special case that the compiler could be smart enough to figure out. Either way we're stuck with it! – Simon_Weaver Aug 08 '21 at 21:58

8 Answers8

317

You missed some breaks there:

switch (searchType)
{
    case "SearchBooks":
        Selenium.Type("//*[@id='SearchBooks_TextInput']", searchText);
        Selenium.Click("//*[@id='SearchBooks_SearchBtn']");
        break;

    case "SearchAuthors":
        Selenium.Type("//*[@id='SearchAuthors_TextInput']", searchText);
        Selenium.Click("//*[@id='SearchAuthors_SearchBtn']");
        break;
}

Without them, the compiler thinks you're trying to execute the lines below case "SearchAuthors": immediately after the lines under case "SearchBooks": have been executed, which isn't allowed in C#.

By adding the break statements at the end of each case, the program exits each case after it's done, for whichever value of searchType.

BoltClock
  • 700,868
  • 160
  • 1,392
  • 1,356
  • 36
    For me, I sat there looking at this code and my own until I finally realised I was actually missing the break on the very last case, for anyone who finds that helpful. – somoso Mar 23 '13 at 12:52
  • @somoso I had the break *inside* the braces of a nest `if` statement, so I couldn't spot it quickly. – PeterX Feb 13 '15 at 08:05
  • 18
    And what if my solution requires no `break` because it needs to fall through on some circumstances?! – Black Oct 26 '17 at 21:31
  • @Black: Then you can't use a switch statement. C# just doesn't allow a case to fall through when it has its own logic to execute. – BoltClock Oct 27 '17 at 04:19
  • 15
    wow, what the heck were the C# devs thinking?! It works in every programming language I know, but not in C#. – Black Oct 27 '17 at 07:05
  • It works fine in C#. You just need to add a default: break; at the end. – j riv Nov 28 '17 at 02:42
  • 2
    @j riv: No, it doesn't. There is never a situation where an empty default case is required in a switch statement. C# doesn't allow this, period, unless you're saying this has changed in an upcoming revision of the spec. – BoltClock Nov 28 '17 at 04:11
  • 9
    The one thing this answer is missing is the fact that you can still do C-Style fall-throughs using `goto case "some String"`. – NH. Jan 03 '18 at 22:00
  • 4
    I never realized this. I always thought VB was missing the case fall-through feature that C++ has. Now I find out that C# doesn't have it either, AND to add insult to injury, you have to type the break statement. It won't even autofill it. – Brain2000 Jan 31 '18 at 00:38
  • 1
    @Black: If your solution requires no `break` then you write the two (or more) `case` statements together with no code in between. This way C# allows you to fall through `case` statements – Juan Castano Apr 03 '18 at 05:53
  • 7
    C# does this the right way. C# devs are geniuses. The fall-through mechanism that other languages like C++ use is a mistake. C#'s requirement of an explicit fall through via 'goto case' is safer, more powerful, and clearer. Not only can you achieve the 'fall through' behavior, you can explicitly 'fall to any case explicitly'. Falling through is a lazy joke in other languages. C# was designed to fix all this weird and error prone quirks of older languages. – Triynko Jan 03 '20 at 13:42
154

You need to break;, throw, goto, or return from each of your case labels. In a loop you may also continue.

        switch (searchType)
        {
            case "SearchBooks":
                Selenium.Type("//*[@id='SearchBooks_TextInput']", searchText);
                Selenium.Click("//*[@id='SearchBooks_SearchBtn']");
                break;

            case "SearchAuthors":
                Selenium.Type("//*[@id='SearchAuthors_TextInput']", searchText);
                Selenium.Click("//*[@id='SearchAuthors_SearchBtn']");
                break;
        }

The only time this isn't true is when the case labels are stacked like this:

 case "SearchBooks": // no code inbetween case labels.
 case "SearchAuthors":
    // handle both of these cases the same way.
    break;
agent-j
  • 27,335
  • 5
  • 52
  • 79
  • 8
    `continue` is possible as well – Tobias Valinski Feb 04 '14 at 15:09
  • 4
    Can anyone explain -why- this is? I feel like there are legitimate use cases to execute code and have control continue fall through to the next case. – YasharBahman Feb 05 '14 at 07:07
  • 14
    @YasharBahman, I think there are far more bugs than intended cases in languages that support case fall-through. In C#, the language allows you to `goto case "SearchBooks";` so you have the ability to do what you need to do without losing much expressiveness or adding unexpected bugs. – agent-j Feb 05 '14 at 14:08
  • 3
    @agent-j I see. Thanks, that makes a lot of sense. Also, I didn't know you could use goto like that, that's really cool! (although, I think I'll always be weary of using it since my professors have convinced me that I will spontaneously combust if I do) – YasharBahman Feb 06 '14 at 09:03
  • 5
    Why isn't this one the accepted answer? It tells more about what options you have for a switch statement plus giving the answer to the question. – DotNet Programmer Oct 30 '15 at 16:35
  • @agent-j just come across this as was wondering why you still need the break statement if it's not allowed - this makes so much sense - the amount of times I've coded something in php or c++ and it's dropped through all the switch statements and I'm like why on earth is it doing that only to find I've missed one break; statement somewhere. Also that goto case function is so handy - I take it using that you could have it skip an entire case then like switch (in) { case 1 : value = "Hello" ; goto case "3" ; case 2 : value = "Goodbye" ; goto case "3" ; case 3 : Debug.Log ( value ) ; } – TheKLF99 Apr 27 '20 at 07:20
45

You can do more than just fall through in C#, but you must utilize the "dreaded" goto statement. For example:

switch (whatever)
{
  case 2:
    Result.Write( "Subscribe" );
    break;
  case 1:
    Result.Write( "Un" );
    goto case 2;
}
Darwin Airola
  • 919
  • 8
  • 11
14

You need to add a break statement:

switch (searchType)
{
case "SearchBooks":
    Selenium.Type("//*[@id='SearchBooks_TextInput']", searchText);
    Selenium.Click("//*[@id='SearchBooks_SearchBtn']");
    break;
case "SearchAuthors":
    Selenium.Type("//*[@id='SearchAuthors_TextInput']", searchText);
    Selenium.Click("//*[@id='SearchAuthors_SearchBtn']");
    break;
}

This assumes that you want to either handle the SearchBooks case or the SearchAuthors - as you had written in, in a traditional C-style switch statement the control flow would have "fallen through" from one case statement to the next meaning that all 4 lines of code get executed in the case where searchType == "SearchBooks".

The compiler error you are seeing was introduced (at least in part) to warn the programmer of this potential error.

As an alternative you could have thrown an error or returned from a method.

Justin
  • 84,773
  • 49
  • 224
  • 367
7

At the end of each switch case, just add the break-statement to resolve this problem

switch (manu)
{
    case manufacturers.Nokia:
        _phanefact = new NokiaFactory();
        break;

    case manufacturers.Samsung:
        _phanefact = new SamsungFactory();
        break;  
}
shapiro yaacov
  • 2,308
  • 2
  • 26
  • 39
Debendra Dash
  • 5,334
  • 46
  • 38
5

You missed break statements. Don't forget to use break-statements even in the default case.

switch (searchType)
{
    case "SearchBooks":
        Selenium.Type("//*[@id='SearchBooks_TextInput']", searchText);
        Selenium.Click("//*[@id='SearchBooks_SearchBtn']");
        break;
    case "SearchAuthors":
        Selenium.Type("//*[@id='SearchAuthors_TextInput']", searchText);
        Selenium.Click("//*[@id='SearchAuthors_SearchBtn']");
        break;
    default:
        Console.WriteLine("Default case handling");
        break;
}
Kresten
  • 100
  • 2
  • 9
Husnain Shabbir
  • 516
  • 5
  • 12
4

Since it wasn't mentioned in the other answers, I'd like to add that if you want case SearchAuthors to be executed right after the first case, just like omitting the break in some other programming languages where that is allowed, you can simply use goto.

switch (searchType)
{
    case "SearchBooks":
    Selenium.Type("//*[@id='SearchBooks_TextInput']", searchText);
    Selenium.Click("//*[@id='SearchBooks_SearchBtn']");
    goto case "SearchAuthors";

    case "SearchAuthors":
    Selenium.Type("//*[@id='SearchAuthors_TextInput']", searchText);
    Selenium.Click("//*[@id='SearchAuthors_SearchBtn']");
    break;
}
Kresten
  • 100
  • 2
  • 9
Ouissal
  • 1,519
  • 2
  • 18
  • 36
0
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Case_example_1
{
    class Program
    {
        static void Main(string[] args)
        {
            Char ch;
            Console.WriteLine("Enter a character");
            ch =Convert.ToChar(Console.ReadLine());
            switch (ch)
            {
                case 'a':
                case 'e':
                case 'i':
                case 'o':
                case 'u':
                case 'A':
                case 'E':
                case 'I':
                case 'O':
                case 'U':

                    Console.WriteLine("Character is alphabet");
                    break;

                default:
                    Console.WriteLine("Character is constant");
                    break;

            }

            Console.ReadLine();

        }
    }
}
  • 1
    You should put some words or something to explain why this a solution. Since you don't explain why you need the breaks for some and not others. – DotNet Programmer Oct 30 '15 at 16:37
  • 3
    did you mean "consonant"? – maraaaaaaaa Feb 05 '16 at 15:07
  • 1
    1. I think you meant "vowel" vs. "alphabet". 2. You might want to change `switch (ch)` to the following. `char vowelCheckChar = ( (Char.ToLower(ch) == 'y') ? ( ((new Random()).Next(2) == 0) ? ch : 'a' ) : ch ); // char vowelCheckChar = switch (vowelCheckChar)` Sorry, had to. ;) – Tom May 02 '17 at 14:58