Switch design
The switch/case construct evaluates some expression and compares its value with a set of values. And if the values match, it executes a certain code...:
The switch construct has the following formal definition:
switch (expression)
{
case value1:
code executed if expression has value1
break;
case value2:
code to be executed if the expression has value2
break;
//.............
case valueN:
code to be executed if the expression has valueN
break;
default:
code executed if the expression has none of the above values
break;
}
The keyword switch is followed by the expression to be compared in parentheses. The value of this expression is sequentially compared with the values placed after the case operator. And if a match is found, a certain block of caѕe will be executed.
One of the transition operators must be placed at the end of each case block: break, goto case or return. As a rule, the break operator is used. When it is used, other case blocks will not be executed.
For example:
string name = “Tom”;
switch (name)
{
case “Bob”:
Console.WriteLine(“Your name is Bob”);
break;
case “Tom”:
Console.WriteLine(“Your name is Tom”);
break;
case “Sam”:
Console.WriteLine(“Your name is Sam”);
break;
}
In this case, the switch construct sequentially compares the value of the name variable with the set of values that are specified after the case statements. Since here the value of the name variable is the string “Tom”, the block will be executed
case “Tom”:
Console.WriteLine(“Your name is Tom”);
break;
Accordingly, we will see on the console
Your name is Tom
If the value of the name variable does not match any value after the case operators, then none of the case blocks will be executed. However, if even in this case we still need to perform some actions, we can add an optional default block to the switch construct. For example:
string name = “Alex”;
switch (name)
{
case “Bob”:
Console.WriteLine(“Your name is Bob”);
break;
case “Tom”:
Console.WriteLine(“Your name is Tom”);
break;
case “Sam”:
Console.WriteLine(“Your name is Sam”);
break;
default:
Console.WriteLine(“Unknown name”);
break;
}
In this case, none of the values after the case statements match the value of the name variable, so the default block will be executed:
default:
Console.WriteLine(“Unknown name”);
break;
However, if we want another case block to be executed after the current case block, we can use the goto case operator instead of break:
int number = 1;
switch (number)
{
case 1:
Console.WriteLine(“case 1”);
goto case 5; // switch to case 5
case 3:
Console.WriteLine(“case 3”);
break;
case 5:
Console.WriteLine(“case 5”);
break;
default:
Console.WriteLine(“default”);
break;
}
Return value from switch
The switch construct allows you to return some value. The return operator can be used to return a value in case blocks. For example, let's define the following method:
int DoOperation(int op, int a, int b)
{
switch (op)
{
case 1: return a + b;
case 2: return a - b;
case 3: return a * b;
default: return 0;
}
}
A numeric operation code and two operands are passed to the DoOperation() method. Depending on the operation code, a certain operation is performed on the operands and its result is returned from the method. To give an example, the default method returns 0 from the method if the operation code is not 1, 2, or 3.
We can then call the method:
int DoOperation(int op, int a, int b){ switch (op)
{
case 1: return a + b;
case 2: return a - b;
case 3: return a * b;
default: return 0;
}
}
int result1 = DoOperation(1, 10, 5); // 15
Console.WriteLine(result1); // 15
int result2 = DoOperation(3, 10, 5); // 50
Console.WriteLine(result2); // 50
Getting the result from switch
Although the switch construct in the above example works fine, we can shorten it and get the result not directly from the switch construct:
int DoOperation(int op, int a, int b)
{
int result = op switch {
1 => a + b,
2 => a - b,
3 => a * b,
_ => 0
};
return result;
}
Now the case operator is not required, but the arrow => operator is placed after the compared value. The value to the right of the arrow acts as the return value. In addition, the handwriting _ is used instead of the default operator. As a result, the result of the switch construct will be assigned to the result variable.
Of course, we can return the result from the method without assigning the result variable of the switch construct:
int DoOperation(int op, int a, int b)
{
return op switch
{
1 => a + b,
2 => a - b,
3 => a * b,
_ => 0
};
}
Or make the method even shorter:
int DoOperation(int op, int a, int b) => op switch
{
1 => a + b,
2 => a - b,
3 => a * b,
_ => 0
};
Note that this simplification only applies to switch constructs that return some values, as in the example above.
It is worth noting that when returning a value from a method, the method should return a value anyway. For example, the following version of the method will not work
int DoOperation(int op, int a, int b)
{
return op switch
{
1 => a + b,
2 => a - b,
3 => a * b
};
}
This version of the method returns a value if the operation code is 1, 2 or 3. But what if a value of 4 or some other value is passed in? Therefore, this version of the method will not even compile. So we need to provide for returning a value from the method in all possible cases. That is, we can, as in the example above, add a default block to the switch construct, which will return the value in all other cases.