Error 1 control cannot fall through from one case label case 1 to another

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 "Con...

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's user avatar

asked Jul 14, 2011 at 16:28

Maya's user avatar

3

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.

answered Jul 14, 2011 at 16:29

BoltClock's user avatar

BoltClockBoltClock

687k158 gold badges1373 silver badges1349 bronze badges

11

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;

answered Jul 14, 2011 at 16:30

agent-j's user avatar

agent-jagent-j

27k5 gold badges51 silver badges79 bronze badges

6

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;
}

answered Mar 15, 2016 at 22:05

Darwin Airola's user avatar

3

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.

answered Jul 14, 2011 at 16:30

Justin's user avatar

JustinJustin

83.8k48 gold badges221 silver badges360 bronze badges

2

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's user avatar

answered Dec 22, 2017 at 5:48

Debendra Dash's user avatar

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;
}

kres0345's user avatar

kres0345

902 silver badges8 bronze badges

answered Apr 9, 2018 at 3:51

Husnain Shabbir's user avatar

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;
}

kres0345's user avatar

kres0345

902 silver badges8 bronze badges

answered Apr 25, 2019 at 12:12

Ouissal's user avatar

OuissalOuissal

1,4692 gold badges16 silver badges36 bronze badges

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();

        }
    }
}

answered Aug 27, 2015 at 3:06

Bob Maharjan's user avatar

3

Permalink

Cannot retrieve contributors at this time

description title ms.date f1_keywords helpviewer_keywords ms.assetid

Compiler Error CS0163

Compiler Error CS0163

07/20/2015

CS0163

CS0163

00139dcf-33cd-45ea-bf80-d6f26b10a5d2

Compiler Error CS0163

Control cannot fall through from one case label (‘label’) to another

When a switch statement contains more than one switch section, you must explicitly terminate each section, including the last one, by using one of the following keywords:

  • return
  • goto
  • break
  • throw

If you want to implement «fall through» behavior from one section to the next, use goto case #.

The following sample generates CS0163.

// CS0163.cs  
public class MyClass  
{  
    public static void Main()  
    {  
        int i = 0;  
  
        switch (i)   // CS0163  
        {  
            // Compiler error CS0163 is reported on the following line.  
            case 1:  
                i++;  
            // To resolve the error, uncomment one of the following example statements.  
            // return;  
            // break;  
            // goto case 3;  
  
            case 2:  
                i++;  
                return;  
  
            case 3:  
                i = 0;  
                return;  
  
            // Compiler error CS0163 is reported on the following line.  
            default:  
                Console.WriteLine("Default");  
                // To resolve the error, uncomment the following line:  
            //break;  
        }  
    }  

RRS feed

  • Remove From My Forums
  • Question

  • Got the error as the title.

    switch (buffer)
                            {
                                case "1": 
                                    {
                                        if (option1)
                                        {
                                            Option_2_1();
                                            break;
                                        }
                                    }
                                case "2": 
                                    {
                                        Option_2_2();
                                        break;
                                    }

    Thanks.

Answers

  • Add break; after if in the first case. Break must be in each execution path.

    switch (buffer)
    {
        case "1":
        {
             if (option1)
             {
                 Option_2_1();
                 break;
             }
             break; 
         }
         case "2":
         {
             Option_2_2();
             break;
         }
    }
    • Marked as answer by
      ardmore
      Thursday, May 9, 2013 1:31 PM

All replies

  • You need to add the break in the case block like this:

    switch (buffer)
                            {
                                case "1": 
                                    
                                     if (option1)
                                     {
                                         Option_2_1();
                                          
                                     }
                                     break; // HERE!
                                case "2": 
                                        Option_2_2();
                                        break;

    Noam B.



    Do not Forget to Vote as Answer/Helpful, please. It encourages us to help you…

    • Proposed as answer by
      Noam B
      Thursday, May 9, 2013 2:37 PM

  • Add break; after if in the first case. Break must be in each execution path.

    switch (buffer)
    {
        case "1":
        {
             if (option1)
             {
                 Option_2_1();
                 break;
             }
             break; 
         }
         case "2":
         {
             Option_2_2();
             break;
         }
    }
    • Marked as answer by
      ardmore
      Thursday, May 9, 2013 1:31 PM

  • try code

                switch (buffer)
                {
                    case "1":
                        {
                            if (option)
                            {
                                //Option_2_1();
                            }
                            break;
                        }
                    case "2":
                        {
                            //Option_2_2();
                            break;
                        }
                }

    Regards

    Mohit Gupta

    • Proposed as answer by
      Mohit Kumar Gupta
      Thursday, May 9, 2013 1:36 PM

C# Compiler Error

CS0163 – Control cannot fall through from one case label (‘label’) to another

Reason for the Error

You will receive this error when you DONOT explicitly terminate a switch statement in C#.

For example, try compiling the below code snippet.

using System;

namespace ConsoleApp2
{
    class Program
    {
        public static void Main()
        {
            int val = 10;
            switch(val)
            {
                case 1: Console.WriteLine("Case 1");
                case 2: break;
            }
        }

    }
    
}

You will receive the error code CS0163 in C# for the above code snippet because the section (case 1 ) is not terminated explicitly using break.

C# Error CS0163 – Control cannot fall through from one case label ('label') to another

Error CS0163 Control cannot fall through from one case label (‘case 1:’) to another ConsoleApp2 C:UsersSenthilsourcereposConsoleApp1ConsoleApp2Program.cs 12 Active

Solution

When the switch statement contains multiple cases, it will need to be terminated by one of the following keywords : return, goto, break, throw, continue.

The error in the above code can be fixed by adding break to terminate the case 1 as show below.

using System;

namespace ConsoleApp2
{
    class Program
    {
        public static void Main()
        {
            int val = 10;
            switch(val)
            {
                case 1: Console.WriteLine("Case 1");
                    break;
                case 2: break;
            }
        }

    }
    
}

SocialEngineer

29 / 31 / 2

Регистрация: 14.04.2012

Сообщений: 152

1

23.06.2012, 22:26. Показов 3461. Ответов 4

Метки нет (Все метки)


C#
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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
 
namespace WindowsFormsApplication1
{
    public partial class Form1 : Form
    {
        
        Stack<double> st = new Stack<double>();
        double lol;
        
        public Form1()
 
        {
            InitializeComponent();
        }
        private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
        {
            double x;
            if (e.KeyChar < '0' || e.KeyChar > '9')
            {
                st.Push(Convert.ToDouble(e.KeyChar));
            }
            else if (e.KeyChar < 'A' || e.KeyChar > 'Z')
            {
              st.Push(Convert.ToDouble(e.KeyChar));
            }
            else
                switch (e.KeyChar)
                {
                    case '/':
                        x = st.Pop();
                        st.Push(st.Pop() / x);
                        break;
                    case '+':
                        st.Push(st.Pop() / st.Pop());
                        break;
                    case '-':
                        x = st.Pop();
                        st.Push(st.Pop() - x);
                        break;
                        case '*':
                         //
                        break;
                    
                        
                }
        }
 
        private void button1_Click(object sender, EventArgs e)
        {
            lol = st.Peek();
            textBox2.Text = Convert.ToString(lol); 
        }
 
        
    }
 
 }

в конце пишет сообщение,что стек пуст(хотя я провожу манипуляции с 1 текстбоксом)
если в операторе case указать ‘*’ или ‘^’ генерируется какая-то непонятная ошибка:
Error 1 Control cannot fall through from one case label (‘case ‘*’ (0x2A):’) to another C:UsersuserDownloadsProjWindowsFormsApplicati on1WindowsFormsApplication1Form1.cs 48 21 WindowsFormsApplication1
P.s сорри за быдлокод,всё ещё учусь

__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь



0



kolorotur

Эксперт .NET

16930 / 12507 / 3286

Регистрация: 17.09.2011

Сообщений: 20,743

23.06.2012, 23:07

2

Цитата
Сообщение от SocialEngineer
Посмотреть сообщение

C#
1
2
3
4
5
6
7
8
            if (e.KeyChar < '0' || e.KeyChar > '9')
            {
                st.Push(Convert.ToDouble(e.KeyChar));
            }
            else if (e.KeyChar < 'A' || e.KeyChar > 'Z')
            {
              st.Push(Convert.ToDouble(e.KeyChar));
            }

Это же тавтология.

Цитата
Сообщение от SocialEngineer
Посмотреть сообщение

Error 1 Control cannot fall through from one case label (‘case ‘*’ (0x2A):’)

Из каждого блока case должен быть явный выход через использование одного или более из:
1. break
2. throw
3. return
4. goto



0



Psilon

Master of Orion

Эксперт .NET

6094 / 4950 / 905

Регистрация: 10.07.2011

Сообщений: 14,522

Записей в блоге: 5

24.06.2012, 12:42

3

SocialEngineer, во-первых, как выше замечено, советую вместо

C#
1
2
3
4
5
6
7
8
if (e.KeyChar < '0' || e.KeyChar > '9')
            {
                st.Push(Convert.ToDouble(e.KeyChar));
            }
            else if (e.KeyChar < 'A' || e.KeyChar > 'Z')
            {
              st.Push(Convert.ToDouble(e.KeyChar));
            }

написать

C#
1
2
if (Char.IsLetterOrDigit(e.KeyChar)
   st.Push(Convert.ToDouble(e.KeyChar));

насчет ошибки

Error 1 Control cannot fall through from one case label (‘case ‘*’ (0x2A):’)

Попробуйте хотя бы пустой оператор вставить

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
switch (e.KeyChar)
                {
                    case '/':
                        x = st.Pop();
                        st.Push(st.Pop() / x);
                        break;
                    case '+':
                        st.Push(st.Pop() / st.Pop());
                        break;
                    case '-':
                        x = st.Pop();
                        st.Push(st.Pop() - x);
                        break;
                    case '*':
                         ;
                         //
                        break;              
                }



0



kolorotur

Эксперт .NET

16930 / 12507 / 3286

Регистрация: 17.09.2011

Сообщений: 20,743

24.06.2012, 13:16

4

Цитата
Сообщение от Psilon
Посмотреть сообщение

C#
1
2
if (Char.IsLetterOrDigit(e.KeyChar)
 st.Push(Convert.ToDouble(e.KeyChar));

По вашей логике — брать цифру или букву.
По логике автора — брать что угодно.

Так задумано или нет — не знаю, но во втором случае условия можно вообще убрать — одно из них всегда будет true, а выполняется один и тот же код.



0



Psilon

Master of Orion

Эксперт .NET

6094 / 4950 / 905

Регистрация: 10.07.2011

Сообщений: 14,522

Записей в блоге: 5

24.06.2012, 15:58

5

kolorotur, у него же в коде откидывается промежуток от 0 до 9 и все буквы. Тогда просто отрицание добавить, получится то же самое

C#
1
2
if (!Char.IsLetterOrDigit(e.KeyChar)
 st.Push(Convert.ToDouble(e.KeyChar));



0



Содержание

  1. Error 1 control cannot fall through from one case label case 1 to another
  2. Вопрос
  3. Error 1 control cannot fall through from one case label case 1 to another
  4. Вопрос

Error 1 control cannot fall through from one case label case 1 to another

Вопрос

I am peresenting the data on the page using SPGridView.My requirement is i need to add add checkboxfield as a column to the existing SPGridView.For that what i have done is i have wrritten code as below in the web part as

TemplateField checkboxCol = new TemplateField();
checkboxCol.HeaderText = «Select All»;
checkboxCol.ItemTemplate = new CustomSPGridViewTemplate(ListItemType.Item, «Select All»);
spgw.Columns.Add(checkboxCol);
this.Controls.Add(spgw);

in the CreateChildControls method.After that i have created another class and i have written as below

class CustomSPGridViewTemplate : ITemplate
<
ListItemType templateType;
string columnName;

public CustomSPGridViewTemplate(ListItemType type, string colname)
<
templateType = type;
columnName = colname;
>
#region ITemplate Members

public void InstantiateIn(Control container)
<
Literal lc = new Literal();
switch (templateType)
<
case ListItemType.Header:
lc.Text = » » + columnName + » «;
container.Controls.Add(lc);
break;
case ListItemType.Item:
CheckBox checkBox = new CheckBox();
checkBox.ID = «SelectAllID»;
checkBox.Visible = true;
//checkBox.DataBinding += new EventHandler(checkBox_DataBinding);
container.Controls.Add(checkBox);
>
>

But when i compile it is giving error as

‘Control cannot fall through from one case label (‘case 2:’) to another’.Have you ever come across this scenario

Источник

Error 1 control cannot fall through from one case label case 1 to another

Вопрос

I am peresenting the data on the page using SPGridView.My requirement is i need to add add checkboxfield as a column to the existing SPGridView.For that what i have done is i have wrritten code as below in the web part as

TemplateField checkboxCol = new TemplateField();
checkboxCol.HeaderText = «Select All»;
checkboxCol.ItemTemplate = new CustomSPGridViewTemplate(ListItemType.Item, «Select All»);
spgw.Columns.Add(checkboxCol);
this.Controls.Add(spgw);

in the CreateChildControls method.After that i have created another class and i have written as below

class CustomSPGridViewTemplate : ITemplate
<
ListItemType templateType;
string columnName;

public CustomSPGridViewTemplate(ListItemType type, string colname)
<
templateType = type;
columnName = colname;
>
#region ITemplate Members

public void InstantiateIn(Control container)
<
Literal lc = new Literal();
switch (templateType)
<
case ListItemType.Header:
lc.Text = » » + columnName + » «;
container.Controls.Add(lc);
break;
case ListItemType.Item:
CheckBox checkBox = new CheckBox();
checkBox.ID = «SelectAllID»;
checkBox.Visible = true;
//checkBox.DataBinding += new EventHandler(checkBox_DataBinding);
container.Controls.Add(checkBox);
>
>

But when i compile it is giving error as

‘Control cannot fall through from one case label (‘case 2:’) to another’.Have you ever come across this scenario

Источник

These C# examples cover the switch statement. It is possible to switch on value types and strings.

Switch. This construct tests a variable against a set of constants.

The compiler uses lookup table optimizations. A switch makes a decision. It is sometimes faster than if.

Example. This program uses a switch. It introduces an int local. It tests the int against two constants: 1 and 5. As it equals 5, we reach the second case. And 5 is printed.

Caution: Not every variable can be used in a switch. Most built-in value types, like int or char, work.

Strings: A switch can handle strings. These are implemented in a different way. They use a hidden Dictionary.

Based on:

.NET 4.5

C# program that uses switch

using System;

class Program
{
    static void Main()
    {
	int value = 5;
	switch (value)
	{
	    case 1:
		Console.WriteLine(1);
		break;
	    case 5:
		Console.WriteLine(5);
		break;
	}
    }
}

Output

5

Another example. This includes curly brackets and the default case. The program accepts an int from the user (with ReadLine). It then tests it for six values.

Here: We see how the curly brackets are used in the switch cases. And we combine some of the case statements.

C# program that uses int switch

class Program
{
    static void Main()
    {
	while (true)
	{
	    System.Console.WriteLine("Type number and press Return");
	    try
	    {
		int i = int.Parse(System.Console.ReadLine());
		switch (i)
		{
		    case 0:
		    case 1:
		    case 2:
			{
			    System.Console.WriteLine("Low number");
			    break;
			}
		    case 3:
		    case 4:
		    case 5:
			{
			    System.Console.WriteLine("Medium number");
			    break;
			}
		    default:
			{
			    System.Console.WriteLine("Other number");
			    break;
			}
		}
	    }
	    catch
	    {
	    }
	}
    }
}

Output

Type number and press Return
5
Medium number
Type number and press Return
2
Low number
Type number and press Return
500
Other number

Strings. Often we switch on values, like numbers. The contents of strings are not value types—they are collections of characters. But with special support, we switch on strings too.

Note: The C# compiler detects a string switch and can optimize it with a Dictionary lookup.

Note 2: Small string switches, like this one with just 3 cases, are often not compiled into Dictionaries. Performance is better this way.

C# program that switches on string

using System;

class Program
{
    static void Main()
    {
	string value = "turnip";
	// ... Switch on the string.
	switch (value)
	{
	    case "lettuce":
		Console.WriteLine("LETTUCE");
		break;
	    case "squash":
		Console.WriteLine("SQUASH");
		break;
	    case "turnip":
		Console.WriteLine("TURNIP");
		break;
	}
    }
}

Output

TURNIP

Types. It is possible to switch on integers or other value types, such as enums or chars. Strings are a reference type, but the C# compiler can handle switches on strings as well.

Switch CharSwitch EnumSwitch String

Case. We cover switch syntax. The switch statement uses somewhat different indentation rules by default. Some cases (default) do not use the case keyword.

Case

Goto. We can use goto statements in switches. These are different from other gotos. With goto we can run multiple cases for a single expression.

Goto, Switch

Break. This keyword is used within switches. And continue may also be used. These two keywords are used also within loops. Sometimes they are used in both loop and switch statements.

BreakContinue

So: Are you breaking out of a switch, or out of the enclosing loop? Scope is important: the deepest construct is broken first.

Double. Some values may not be switched upon. Floating-point values, like doubles, will cause an error in a switch expression. Most classes and custom types will also fail.

Bool: A bool may be used in the expression of a switch. But this is somewhat strange as only true and false are allowed.

Nullable: A nullable type can be used, but only if the nullable type «wraps» a valid switch type like an enum.

C# program that causes switch double error

class Program
{
    static void Main()
    {
	double value = 1.4;
	switch (value)
	{
	    case 1:
		break;
	}
    }
}

Output

Error 1
A switch expression or case label must be a bool, char, string,
integral, enum, or corresponding nullable type....

Nested switch. Sometimes one switch is not enough. But we can nest a switch within another switch, successively testing values. This approach is sometimes helpful.

Nested Switch

But: Our code logic, with nested switches, quickly turns into a mess. With comments, this approach may succeed.

Here: I test the first two elements in an int array with switches. The second element is tested if the first is 4.

C# program that uses nested switch

using System;

class Program
{
    static void Main()
    {
	int[] array = { 4, 10, 14 };
	switch (array[0])
	{
	    case 3:
		Console.WriteLine(3); // Not reached.
		break;

	    case 4:
		Console.WriteLine(4);
		// ... Use nested switch.
		switch (array[1])
		{
		    case 10:
			Console.WriteLine(10);
			break;
		}
		break;
	}
    }
}

Output

4
10

Fall through. Every case must have a break, continue, goto, return or throw at its end. In C# we cannot have cases with statements fall through to the following case.

Goto: We can use the goto statement, as in «goto case 1,» to run both cases on a 0 value. As shown, the program does not compile.

C# program that has fall-through error

using System;

class Program
{
    static void Main()
    {
	int value = 0;
	// ... Every switch statement must be terminated.
	switch (value)
	{
	    case 0:
		Console.WriteLine("Zero");
	    case 1:
		Console.WriteLine("One");
		break;
	}
    }
}

Output

Error 1
Control cannot fall through from one case label ('case 0:') to another

Duplicate cases. A switch can only have unique case labels—each constant value must be distinct. This program will not compile. But it shows us what happens when we have duplicate cases.

C# that has duplicate case

using System;

class Program
{
    static void Main()
    {
	short number = 0;
	// ... Cases may not be duplicated.
	switch (number)
	{
	    case 0:
	    case 0:
		Console.WriteLine("ZERO");
		return;
	    case 1:
		Console.WriteLine("ONE");
		return;
	}
    }
}

Output

Error 1
The label 'case 0:' already occurs in this switch statement

Constants. We must use only constants for case statements. This is a limitation, but it is part of the language specification. The C# compiler is not even tempted.

C# that lacks constant case

using System;

class Program
{
    static void Main()
    {
	int number = 0;
	int test = 10;
	// ... Constant values are required.
	switch (number)
	{
	    case test + 1:
		Console.WriteLine(100);
		return;
	    case 0:
		Console.WriteLine(0);
		return;
	}
    }
}

Output

Error 1
A constant value is expected

Benchmark. A switch statement helps optimize some programs. Suppose a method that must return a value based on a small range of inputs. We can use switch to test these values.

Here: Method 1 uses a switch statement. But method 2 instead uses a series of if-statements.

Note: The benchmark shows that the switch statement version is slightly faster. Those nanoseconds may come in handy someday.

C# that benchmarks switch

using System;
using System.Diagnostics;

class Program
{
    static int Method1(int v)
    {
	switch (v)
	{
	    case 0:
		return 10;
	    case 1:
		return -1;
	    case 2:
		return 20;
	    default:
		return 0;
	}
    }

    static int Method2(int v)
    {
	if (v == 0) return 10;
	if (v == 1) return -1;
	if (v == 2) return 20;
	return 0;
    }

    static void Main()
    {
	Method1(0); Method2(0);
	const int max = 100000000;

	var s1 = Stopwatch.StartNew();
	for (int i = 0; i < max; i++)
	{
	    Method1(0);
	    Method1(1);
	    Method1(2);
	    Method1(3);
	}
	s1.Stop();
	var s2 = Stopwatch.StartNew();
	for (int i = 0; i < max; i++)
	{
	    Method2(0);
	    Method2(1);
	    Method2(2);
	    Method2(3);
	}
	s2.Stop();
	Console.WriteLine(((double)(s1.Elapsed.TotalMilliseconds * 1000000) /
	    max).ToString("0.00 ns"));
	Console.WriteLine(((double)(s2.Elapsed.TotalMilliseconds * 1000000) /
	    max).ToString("0.00 ns"));
	Console.Read();
    }
}

Results

9.25 ns    [switch]
9.85 ns    [if]

Speed. Switch can be implemented with a jump table in the intermediate language. Large switches can be much faster than long series of if-else statements. We provide more benchmarks.

1. If and switch. The if-statement sometimes performs better than the switch. Testing is essential.

If, Switch Comparison

2. Regex and switch. The switch statement can be used to replace a Regex method call. This can make programs much faster.

Regex, Switch

3. Intermediate language: Switch is often implemented at a lower level with the switch opcode. We show an example.

IL: switch

Usage. Should we use switches everywhere? This is probably a bad idea. With polymorphism, we abstract selections with virtual methods and inheritance. This leads to cleaner code.

Virtual

So: If you want to use switches everywhere in your code, go ahead. But don’t expect to be admired for it.

Refactoring. We consider a quote from the book Refactoring, an excellent treatise on how to improve code so it is not terrible. Well-designed code is easier to maintain.

The problem with switch statements is essentially that of duplication. Often you find the same switch statement scattered around a program in different places. If you add a new clause to the switch, you have to find all these switch statements and change them.

Refactoring: Improving the Design of Existing Code

My thoughts. Switches often outperform if-statements. But more importantly, they help with code design. They enforce all values tested are constants.

Symmetry. This construct imparts a greater sense of symmetry. Switches test value types and strings. They speed up selections. And with them, we write clearer code.


Related Links

Adjectives
Ado
Ai
Android
Angular
Antonyms
Apache
Articles
Asp
Autocad
Automata
Aws
Azure
Basic
Binary
Bitcoin
Blockchain
C
Cassandra
Change
Coa
Computer
Control
Cpp
Create
Creating
C-Sharp
Cyber
Daa
Data
Dbms
Deletion
Devops
Difference
Discrete
Es6
Ethical
Examples
Features
Firebase
Flutter
Fs
Git
Go
Hbase
History
Hive
Hiveql
How
Html
Idioms
Insertion
Installing
Ios
Java
Joomla
Js
Kafka
Kali
Laravel
Logical
Machine
Matlab
Matrix
Mongodb
Mysql
One
Opencv
Oracle
Ordering
Os
Pandas
Php
Pig
Pl
Postgresql
Powershell
Prepositions
Program
Python
React
Ruby
Scala
Selecting
Selenium
Sentence
Seo
Sharepoint
Software
Spellings
Spotting
Spring
Sql
Sqlite
Sqoop
Svn
Swift
Synonyms
Talend
Testng
Types
Uml
Unity
Vbnet
Verbal
Webdriver
What
Wpf

Time to cover yet another construct of the C# language. In this series, we’ve already covered the C# list, array, and string, to name a few. Today’s post is a little bit different, though. Its subject isn’t a data structure or type, but instead, a decision structure: the C# switch statement.

In this post you’ll learn all about the switch statement. What is it, how should you use it, and when should be careful using it?

Le’s get started!

C# Switch Statement: What Is It?

The switch is a selection (or decision) statement. It chooses a single section to execute, based on the value of a test variable. Consider the following example:

static void PrintPostInfo(Post post)
{
    switch (post.Status)
    {
        case PostStatus.Draft:
            Console.WriteLine("The draft for the post {0} was last edited on {1}.", post.Title, post.Updated);
            break;

        case PostStatus.Published:
            Console.WriteLine("The post{0} was published on {1}. It has received {2} comments", post.Title, post.Published, post.CommentCount);
            break;

        case PostStatus.Scheduled:
            Console.WriteLine("The post {0} is scheduled for publication on {1}", post.Title, post.PublicationDate);
            break;

        case PostStatus.Deleted:
            Console.WriteLine("The post {0} was deleted on {1}", post.Title, post.DeleteDate);
            break;

        default:
            throw new InvalidEnumArgumentException(nameof(post), (int)post.Status, typeof(PostStatus));
    }
}

This is a simple method that prints a message to the console, based on the value of a property from the object received as a parameter. Here’s the equivalent code using if statements:

static void PrintPostInfo(Post post)
{
    if (post.Status == PostStatus.Draft)
    {
        Console.WriteLine("The draft for the post {0} was last edited on {1}.", post.Title, post.Updated);
    }
    else if (post.Status == PostStatus.Published)
    {
        Console.WriteLine("The post{0} was published on {1}. It has received {2} comments", post.Title, post.Published, post.CommentCount);
    }
    else if (post.Status == PostStatus.Scheduled)
    {
        Console.WriteLine("The post {0} is scheduled for publication on {1}", post.Title, post.PublicationDate);
    }
    else if (post.Status == PostStatus.Deleted)
    {
        Console.WriteLine("The post {0} was deleted on {1}", post.Title, post.DeleteDate);
    }
    else
    {
        throw new InvalidEnumArgumentException(nameof(post), (int)post.Status, typeof(PostStatus));
    }
}

How to Use the Switch Statement

With the “what” out of the way, time to get to the “how.” Now we’re going to show how to actually use this structure in practice, starting out by breaking it down into its component parts.

The Anatomy of the C# Switch

The “switch”?statement begins?with the match expression, followed by n switch sections,?n being a number equals to or greater than 1. We’re now going to cover each of these parts in detail.

1. The Match Expression

The match expression is where you specify the value to be matched against the possible values. It follows this syntax:

switch (expression)

What exactly is this expression?

For versions through C# 6.0, it could be any expression that returns either a bool, a char, a string, or even an enum value (which is a very common use case). It could also be an integral value (for instance, a long or an int).

Starting at the 7th version of C# on, it’s possible to use any non-null expression as a match expression.?More on that later.

After that, what follows is one or more switch sections. A switch section, in its turn, contains one or more labels.

2. The Switch Section(s)

A switch statement contains at least one switch section.? A switch section, in turn, contains one or more case labels.

Each label is then followed by one or more statements. The C# language only allows a single switch section to be executed in any switch statement. For instance, the following code won’t compile:

static void PrintMessage(string message, MessageType type)
{
    switch (type)
    {
        case MessageType.Info:
            PrintInfo(message);
            break;

        case MessageType.Error:
            PrintError(message);

        case MessageType.Question:
            PrintQuestion(message);
            break;
    }
}

The error message we get is “Control cannot fall through from one case label (‘case MessageType.Error:’) to another.”

How do we fix this? Easy: let’s just add a break to the second switch section.

static void PrintMessage(string message, MessageType type)
{
    switch (type)
    {
        case MessageType.Info:
            PrintInfo(message);
            break;

        case MessageType.Error:
            PrintError(message);
            break;

        case MessageType.Question:
            PrintQuestion(message);
            break;
    }
}

I bet you probably already knew that. But here’s the thing. There’s nothing special about the break instruction.

You just have to make sure the control flow stops after the execution of the chosen section. You could use a return or throw an exception instead. For instance, the following version of the code above would work just as well:

static void PrintMessage(string message, MessageType type)
{
    switch (type)
    {
        case MessageType.Info:
            PrintInfo(message);
            return;

        case MessageType.Error:
            PrintError(message);
            return;

        case MessageType.Question:
            PrintQuestion(message);
            return;
    }
}

3. Case Labels

Each label provides a pattern for comparison. These patterns are then tested, in order, against the match expression.

When there is a match, the switch section that has the fist matching label receives control. If all case labels are verified but no matches are found, the default case section receives the control. If no section has the default case label, no statements are executed at all

The sixth version of the C# language only supports constants as case labels. Also, it doesn’t allow the repetition of values.

The implication of this is that, in C# 6, the case labels define values that are mutually exclusive. Because of that, the order of case statements doesn’t matter.

C#_switch_statement_submain

However, C# 7.0 changed things quite a bit.

Starting with this version, C# supports other types of patterns. Because of that, the values defined by the labels don’t need to be mutually exclusive, which means that the match expression can match more than one pattern.

You probably already know where this is going: the order of case statements now matters.

If you write a switch section containing one or more statements that are subsets of statements that appeared previously (or even equivalent to them), you’re going to get the CS8120 compiler error, with the following error message: “The switch case has already been handled by a previous case.”

The C# Switch Default Case

When you use the switch statement, what do you do when the expression value doesn’t match any of the?labels?

First, you must define what that means with respect to your business rules. It might be perfectly okay, or it might represent a mistake. In either case, C# provides the default case for handling those types of situations.

exasperated programmer with her head on a desk resenting code review practices

The “PrintMessage” method we’ve defined receives an enum as a parameter. Although an enum can have any integral type as its underlying type, the default is int.

Given an enum with int as its underlying type, you can cast any int value to the enum type and it will gladly compile. So as long as the compiler is concerned, the following line of code is perfectly valid:

PrintMessage("Why did the chicken cross the road?", (MessageType)123456123);

What happens when we run the code above? Well, nothing.

Since the number we’ve passed isn’t the value of a valid enumeration, the switch doesn’t match it with any switch section. The control flows until the end of the method, and nothing gets printed.

Would that be such a big deal?

Not in this very simple example we’re using, no. But it’s not that hard to imagine a serious, more complex application where each switch section calls a method that runs a critical operation. In that case, it would be an enormous deal to have the process fail to run without giving any warnings. That’s what we call “failing silently.”

In such a situation, it would be far more useful to fail fast by throwing an exception. The following code shows just how to do that:

switch (type)
{
    case MessageType.Info:
        PrintInfo(message);
        break;

    case MessageType.Error:
        PrintError(message);
        break;

    case MessageType.Question:
        PrintQuestion(message);
        break;

    default:
        throw new InvalidEnumArgumentException(nameof(type), (int)type, typeof(MessageType));
}

In this iteration of our example, we’ve reverted the switch sections to using the break instruction instead of return. We’ve also added a new section under the “default” label. Now when someone passes it an integer that doesn’t match with the enumeration values, our method throws an exception of type “InvalidEnumArgumentException.”

Modern Switch: Welcome to Pattern Matching

Throughout this post, we?ve been saying time and time again that the C# switch statements now accept more patterns as case labels values. But what does that really mean, in practice? That?s what this section is going to cover.

First we?re going to briefly cover the constant pattern, a.k.a. the old, regular way. After that, we?ll talk about the type pattern, which is the novelty introduced by C# 7.0

The Switch Constant Pattern

The C# switch “constant pattern” is just a name for the old, regular way of doing things. It’s the way you’re used to, from C# 6.0.

It verifies whether the match expression matches the constant you’ve specified.

And what does ?constant? mean here? According to the docs by Microsoft, any of the following:

  • A bool literal, either true or false.
  • Any integral constant, such as int, long, or a byte.
  • The name of a declared const variable.
  • An enumeration constant.
  • A char literal.
  • A string literal.

The Switch Type Pattern

C# 7.0 introduced the ?type pattern.? This new pattern allows you to easily evaluate and convert between types.

Sure, you still could accomplish the same in older versions of C#, by employing several chained if-statements and casts. But with the switch statement new pattern-matching capabilities, you can do the same with way less code.

The syntax of the type pattern is as follows:

case type varname

According to the docs, those are the instances where the test evaluates to “true”:

  • expr is an instance of the same type as type.
  • expr is an instance of a type that derives from type. In other words, the result of expr can be upcast to an instance of type.
  • expr has a compile-time type that is a base class of type, and expr has a runtime type that is type or is derived from type.
  • The compile-time type of a variable is the variable’s type as defined in its type declaration. The runtime type of a variable is the type of the instance that is assigned to that variable.
  • expr is an instance of a type that implements the type interface.

Let’s consider a quick code example:

private static void PrintUserInformation(object user)
{
    switch (user)
    {
        case Admin admin:
           Console.WriteLine("The user is an admin.");
           break;
        case SuperUser superUser:
           Console.WriteLine("The user is a super user.");
           break;   
        case IUser user:
            Console.WriteLine("The user is any other type of user.");
           break;   
        case null:
           Console.WriteLine("User is null.");
           break;
        default:
  }
}

Suppose our code features an IUser interface, which both the Admin and SuperUser classes implement.

The switch in the code sample above tests an instance of object against some type options. If ?user? is an instance of ?Admin?, then the first section is executed and ?The user is an admin.? is displayed. The same happens for ?SuperUser.?

If ?user? is neither ?Admin? nor ?SuperUser?, though, the instance is tested against the ?IUser? interface, and it?ll be evaluated as true if user is an instance of yet another class that implements the interface.

Now it becomes clear how the order matters when it comes to the type pattern.

If we had put the ?IUser? case label first, then it would match with instances of both ?Admin? and ?SuperUser?, generating wrong results. The general rule here is: order the labels from the most specific to the more general types.

Here Be Dragons: Why You Should Beware When Dealing With the C# Switch

Programming tools and techniques aren’t perfect. They can be used for good, but they’re also abused, and the switch statement is no different.

So what are the potential problems with the C# switch you should be aware of when writing code?

The main issue with this construct is that it’s often used to solve problems for which there are better-suited solutions. For example, people often use the switch statement to do a simple mapping:

static string GetInstrumentForMusician(string musician)
{
    switch (musician)
    {
        case "Jimmy Page":
            return "guitar";

        case "Keith Moon":
            return "drums";

        case "Richard Wright":
            return "Keyboard";

        case "Jack Bruce":
            return "bass guitar";

        default:
            throw new ArgumentException("invalid musician");
    }
}

You could accomplish the same result by using a dictionary:

static string GetInstrumentForMusician(string musician)
{
    var instrument = string.Empty;

    try
    {
        instrument = instruments[musician];
    }
    catch (System.Collections.Generic.KeyNotFoundException)
    {
        throw new ArgumentException(musician + " is not a valid musician.");
    }

    return instrument;
}

Which one is “better”?

That depends on so many factors, it doesn’t even make sense for me to try and give a general answer. As I like to say, write code with readability in mind. If performance becomes an issue, then benchmark the heck out of it and optimize where you need.

The biggest problem with switch statements, in general, is that they can be a code smell. Switch overuse might be a sign that you’re failing to properly employ polymorphism in your code.

If you see the same switch statement repeated across your application, it’s probably time to switch (no pun intended) your approach to the use of polymorphic structures.

Back to You Now

In this post you’ve learned a few things about the switch statement in C#: what is it, what problems it solves, how it’s used and, perhaps more importantly, how it can show you signs of potential problems within your application’s design.

Is this all there is to know about the C# switch? Of course not.

The C# language is always evolving, and things are changing fast these days. The language designers have been adding more capabilities to the switch statement in order to get to a feature called “pattern matching” which is commonly found in functional programming languages (such as F#).

This is just an example of things to come (and some things that are already here). So remember: to stay at the top of your game, never stop sharpening your saw.

You might also be interested in further reading about other C# language concepts:

  • Enums
  • Strings
  • Arrays
  • Dictionaries
  • Interfaces
  • Lists
  • Operators

Learn more how CodeIt.Right can help you automate code reviews and improve the quality of your code.

About the author

Carlos Schults Headshot

Carlos Schults

Contributing Author


Carlos Schults is a .NET software developer with experience in both desktop and web development, and he?s now trying his hand at mobile. He has a passion for writing clean and concise code, and he?s interested in practices that help you improve app health, such as code review, automated testing, and continuous build. You can read more from Carlos at carlosschults.net.

Related

Понравилась статья? Поделить с друзьями:
  • Error 0xfffe asrock
  • Error 1 lcd h no such file or directory
  • Error 0xfffc this utility is not for this platform
  • Error 1 error msb3073 the command copy
  • Error 0xfff ps vita