Most languages have a version of the switch statement as far as I’m aware; I must admit, I don’t remember one from Spectrum Basic, but ever since then, I don’t think I’ve come across a language that doesn’t have one. The switch statement in C was interesting. For example, the following was totally valid:
[code lang=“c”]
switch (value)
{
case 1:
printf(“hello ”);
case 2:
printf(“world”);
}
If you gave it a value of 1 would print "hello world". When C# came out, they insisted on using breaks at the end of case statements, or having no code (admittedly there were a few bugs in C caused by accidentally leaving break statements out):
``` csharp
int value = 1;
switch (value)
{
case 1:
Console.Write("hello ");
break;
case 2:
Console.Write("world");
break;
}
Anyway, fast forward around 17 years to C# 7.x, and it basically has the same switch statement; in fact, as far as I’m aware, you could write this switch statement in C# 1.1 and it would compile fine. There’s nothing wrong with it, so I imagine MS were thinking why fix it if it’s not broken.
There are limitations, however; for example, what if I want to return the string, like this:
int value = 1;
string greeting = string.Empty;
switch (value)
{
case 1:
greeting = "hello ";
break;
case 2:
greeting = "world";
break;
}
Console.WriteLine(greeting);
Now it looks a bit cumbersome. What if we could write it like this:
int value = 1;
string greeting = value switch
{
1 => "hello ",
2 => "world",
\_ => string.Empty
};
Console.WriteLine(greeting);
From C# 8, you can do just that. The switch statement will return its value. The case syntax is disposed of, and there’s no need for a break statement (which, to be fair, can encourage people to write large swathes of code inside the switch statement - if you don’t believe me then have a look in the Asp.Net Core source!).
And that’s not all. Pattern matching has also been brought in; for example, take the following simple class structure:
interface IAnimal
{
void Eat();
void Sleep();
string Name { get;}
}
class Dog : IAnimal
{
public string Name { get => "Fido"; }
public void Eat()
{
Console.WriteLine("Dog Eats");
}
public void Sleep()
{
Console.WriteLine("Dog Sleeps");
}
}
class Cat : IAnimal
{
public string Name { get => "Lemmy"; }
public void Eat()
{
Console.WriteLine("Cat Eats");
}
public void Sleep()
{
Console.WriteLine("Cat Sleeps");
}
}
We can put that into a switch statement like this:
IAnimal animal = new Cat();
string greeting = animal switch
{
Dog d => $"hello dog {d.Name}",
Cat c => $"hello cat {c.Name}",
\_ => string.Empty
};
Console.WriteLine(greeting);
We can actually do better that this (obviously better is a relative term). Let’s say that we wanted to do something specific for our particular cat:
IAnimal animal = new Cat();
string greeting = animal switch
{
Dog d => $"hello dog {d.Name}",
Cat c when c.Name == "Lemmy" => $"Hello motorcat!",
Cat c => $"hello cat {c.Name}",
\_ => string.Empty
};
Console.WriteLine(greeting);
It’s a bit of a silly and contrived example, but it does illustrate the point; further, if you switch the case statements around for the general and specific form of Cat, you’ll get a compile error!