How to use switch statement with class

The switch statement controls the execution flow using comparison of constant values. This implies that in each case, the possible values are of primitive or Enum types. What can we do if we want to use a custom class as the switch expression? Clearly this is impossible by default, since custom classes are not primitives or Enums. The solution is to use the implicit cast.

Implicit cast

Implicit cast can is implemented using the implicit cast operator. Implicit cast enables, for example, assignment of instance from one type into a variable of other type.

Example of implicitly castable class:

public class Person
{
public string ID { get; set; }

static public implicit operator int (Person person)
{
return int.Parse(person.ID.Substring(0, 1));
}
}

This casting allows this simple assignment:

var person = new Person() {ID = "0-12345678-9"};
int quality = person;

Switch on class

In order to use a class instance as the switch expression we must choose a governing type for the cases (primitive or Enum) and make the original class castable to that type. For example, if we choose a class of type Person and governing type int then we must have an implicit cast from Person to int.

For example, using the class Person:

var person = new Person() {ID = "0-12345678-9"};

switch (person)
{
case 0:
Console.WriteLine("This is a top level person");
break;
case 9:
Console.WriteLine("This is a bottom level person (probably a developer)");
break;
default:
Console.WriteLine("Just a regular person");
break;
}
Advertisement

Implementing switch fall through in C#

In this post I’ll introduce a less known feature of the C# language – the goto expression.

In general, we know that it is not a great idea to use goto statements in code since it raises significantly the chance of ending up with spaghetti code. Reading and understanding of spaghetti code is way more difficult and therefore its maintenance is expensive.

The case we are going to deal with is goto inside single switch statement. It results that all the labels are local – this case is usually much easier to track than distanced labels. The goto statements enable us to implement the fall through capability which is not supported out of the box in C#.

Switch fall through

In C# implicit fall through between cases in C# is not allowed. The reason for disallowing it is simple – implicit fall through is likely to cause bugs since forgetting to place a break is very common mistake. C# switch statements require each case to end with an explicit end point or a sure “never ending” code. End points are explicit expressions that transfers the execution out of the case block, these can be break, goto, throw and return. A never ending code is code that we know for sure during compilation it is never going to exit the block, such as a while loop whose condition is true.

According to these requirements it is clear that implicit fall through is not supported since we provide explicit instruction about how each case ends.

goto statements

goto in C# is simple and consistent with most languages like C and C++. It is based on labels, which are defined in the code by ‘label-name:’ followed by a C# statement. In order to jump to a label we use the goto statement with the label – ‘goto label-name;’’.

This is a simple implementation of a loop with based on goto.

public void GotoBasedLoop()
{
int times = 3;
int i = 0;
start:
if (i >= times)
{
goto end;
}

Console.WriteLine(i);
i++;
goto start;

end:
return;
}

goto statements in switch

As we’ve seen – each case must have an end point or a promise it never ends. It leads that using naïve usage of gotos we can implement the fall through – we place a label at the beginning of every case and use a goto at the end of every case we want to redirect.

Luckily, for this case C# provides a labels like behavior that simplifies the usage. Each case can be redirected to other case using a simple syntax – goto case ‘constant’ or goto default. Using this syntax we can avoid a duplicate label for fall through.

This usage can be exampled by a simple code that “counts” asterisks:

static int GetLength(string s)
{
int x = 0;

switch (s)
{
case "*":
x++;
break;
case "**":
x++;
goto case "*";
case "***":
x++;
goto case "**";
}

return x;
}

As can be seen, each case is redirected to a different case using the built in mechanism.

Summary

Fall through is probably not the most common feature that developers look for. Since implicit fall through is more likely to cause bugs than simplify coding the C# designers decided to leave it out of the language. For those cases where we want to keep things simple – avoid extracting code to a method just for reuse or instead to create code duplication – we can use the simple solution of redirecting cases using goto.