In the previous lecture, we looked at a rather clumsy way of setting up an infinite loop with a switch
inside it.
But even though that approach is probably not a good approach, there is a good approach which actually
uses the switch expression, not switch statement switch expression.
That’s an important distinction and it uses a switch expression in order to informally define a state
machine.
So let’s imagine that you are into treasure hunting and you find a chest, that chest can be locked
or unlocked and you can perform certain actions on the chest.
So the states that the chest can be in are as follows.
The chest can be open, the chest can be closed, and the chest can also be locked.
Locked implies, of course, that the chest is closed, but it’s also locked, which means you have
to have a key.
Now what we can do is we can define the kind of actions that we can perform on the chest so we can open
the chest and we can close the chest.
And now what we can do is we can use the switch expressions syntax, which is available from C-sharp
eight onwards, to basically just define a method which defines all the transitions using the switch
expression syntax.
So in case you’re not familiar with how it looks, let me show you.
So we’re going to have a static method which returns the state of the chest after some transition.
So we’re going to manipulate the chest and when we manipulate the chest, we need to know about the
current state of the chest.
We also need to know about the kind of action that we want to perform on the chest.
And finally, let’s suppose we have an additional Boolean indicating whether or not we have the key
to the chest half key like so.
Okay.
Now since this is a switch expression and not just using a switch statement, what you’ll see is instead
of using curly braces as you would in an ordinary method, this is an expression.
So we’re going to use expression syntax, which means there is an arrow here, just as we have arrows
for expression, methods and expression properties and all that sort of thing.
So it’s basically a simplification.
Now what we do here is we do a switch, but we do a different switch.
We don’t say switch whatever.
Instead we take all the arguments that we want to pattern match against and then we perform the switch.
So we want to pattern match against all the three arguments.
So we want to take a look at chest action and half key.
And here we write the switch keyword after we specify what we actually want to investigate.
And here comes the curly brace.
So now formatting is a little bit broken.
That’s not my fault.
But what we’re going to do is we’re going to take a look at different sets of values.
And for each set of values, we’re going to define which state we are transitioning to.
So let’s suppose that the chest is locked, the chest is locked, and we want to, let’s say, open
the chest now.
Opening the chest when it’s locked is only possible if you have the key.
So if you have the key, if this value is true, then we are in fact unlocking the chest and the resulting
state is open.
Here we go.
So this is a nice condition.
Now imagine the chest is closed, just closed, not locked.
And you want to open it.
So here you would say action dot open.
Now, in this case, it doesn’t really matter whether or not you have the key because the chest is closed.
It’s not locked.
So here we put an underscore because we don’t really care and the chest is going to be open anyway.
Okay.
So let’s take a look at a situation where the chest is open and we want to close it.
Now, there are actually two cases.
If you have the key, then the chest goes into a locked state because you’ve locked it with the key.
But if you don’t have the key, if the value here is false, then it simply becomes closed.
So here is our state machine.
The only thing that’s missing is some sort of default case.
Now, why would you want the default case?
Aren’t we covering all the cases here already?
Well, not really.
Imagine if the state is open and somebody wants to open it.
In this case, nothing should change.
Nothing should happen here.
So there’s going to be an additional underscore case, the kind of default case or catch all case where
we simply return the current state.
So we transition from the current state to the current state.
Basically nothing happens here.
So this is our switch expression.
You’ll notice that it’s different to how ordinary methods look.
It’s completely different because typically you would have a switch inside the curly braces and here
you have the switch and then the curly braces.
But this has allowed us to informally define the state machine.
So we have, as we did before, a set of the states where in the possible transitions and where we end
up with and we also have a guard condition here.
So half key is a guard condition.
So it’s an external dependency that the state machine sort of checks at runtime in order to.
Figure out whether or not a transition is possible.
So it looks at this argument as well and makes its decisions accordingly.
And we have a catch all case just in case somebody tries something that we haven’t accounted for.
So with this state machine defined, let’s actually simulate it.
So I’ll have a chest that is initially locked and then let’s just output lots of states here.
So the chest is chest.
We output the state and then we can unlock the chest with the key.
So we say chest equals manipulate.
So we manipulate the chest, we want to open it and we have the key.
So I’m putting a value of true here.
Now we can say chest is whatever state it is in.
Now let’s suppose that we decide to just close the chest, not lock it, just close.
So I say chest equals manipulate once again, chest here, action would be closed and I don’t have the
key.
So it’s going to be a false here.
We can once again output the state.
And now let’s imagine that I’m trying to close it again.
So the state is already closed after I do this, but I try to do that same thing once again and we get
to see what’s actually going on here.
Okay.
So let’s actually run all of this.
Let’s take a look at what we get here.
Okay.
So as you can see, initially the chest is locked.
Then we open it with a key.
So the chest is open.
Then we close it without using the key.
So the chest is closed.
And when you perform the close on a close, again, nothing changes.
The state is still the same.
So it tells us that the chest is closed.
Now what we’ve looked here is the use of a guard condition.
What we haven’t discussed here is any kind of action, any kind of behavior that happens when you enter
a state or when you exit a state, that sort of thing.
And if you want to have this sort of thing, then unfortunately you have to give up on the nice switch
expression syntax and you have to go back to an ordinary switch statement, which means that you would
typically regress back to something like this.
So you would have some manipulate to which uses just an ordinary switch.
So the syntax here is not as nice as the C-sharp eight syntax up here.
But what you can do with this case is in the default case, for example, you can perform additional
actions because unfortunately what happens in the switch expression is you return a bunch of values,
you return a value here, you return the value here.
So there is no place here to place, let’s say a console right line.
Now of course, you could try to massage it somehow.
You could make wrappers so that in here or in here, you would both invoke something, both maybe output
something to the command line and return a value.
So it is quite possible.
But if you really want to have lots of behaviors as opposed to just formally define transitions, then
this approach, the approach with having just an ordinary switch statement is probably the approach
that you want to go for.
So this kind of approach is also valid.
It’s also something that you can use to define state machines.
But once again, the downside here is that there is no formal definition of a state machine available
for introspection, which means there is no data structure which clearly defines what the states are
and what the associated transitions are and what the guard conditions are.
So you cannot inspect this set of patterns externally and let’s say, make a report or draw a diagram
on the basis of this.
So this is a limitation.
But on the other hand, it’s very nice syntax.
Once again, using the pattern matching approach is very, very good looking.
So if you have simple state machines that do not require things like documentation and whatever, then
you can use switch expressions from C sharp eight and they will make your code a lot nicer to read.
Play Play Play Play Stop Play Start Play information alert