I just learned that a switch statement can't use non-constant conditions. Which is fine and all, I get it. But does that really mean I have to make a big if-else block? It's so ugly I'm crying.
Some context: I'm doing a Unity project and I want to switch on the current animation state. A good way to check the current animation state is to compare hashes, which means I need to calculate the hashes for the animation state. After calculating them I want to switch on them. (Writing this I realized I can paste the resulting hash into a constant, but now I still want an answer)
int state1 = Animator.StringToHash("State1");
int state2 = Animator.StringToHash("State2");
int hash = _myAnimator.GetCurrentAnimatorStateInfo(0).shortNameHash;
switch (hash):
{
case state1:
//DoStuff
break;
case state2:
//Other stuff
break;
}
What's the best way to do this?
You can do this with a dictionary.
Try this:
int state1 = Animator.StringToHash("State1");
int state2 = Animator.StringToHash("State2");
int hash = _myAnimator.GetCurrentAnimatorStateInfo(0).shortNameHash;
var cases = new Dictionary<Func<bool>, Action>()
{
{ () => hash == state1, () => { /* Do stuff */} },
{ () => hash == state2, () => { /* Do other stuff */} },
};
cases
.Where(c => c.Key()) // find conditions that match
.Select(kvp => kvp.Value) //select the `Action`
.FirstOrDefault() // take only the first one
?.Invoke(); // Invoke the action only if not `null`
To make it a little more clean you could define a Switch
class like this:
public class Switch : IEnumerable<Switch.Case>
{
private List<Case> _list = new List<Case>();
public void Add(Func<bool> condition, Action action)
{
_list.Add(new Case(condition, action));
}
IEnumerator<Case> IEnumerable<Case>.GetEnumerator()
{
return _list.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return _list.GetEnumerator();
}
public void Execute()
{
this
.Where(c => c.Condition())
.Select(c => c.Action)
.FirstOrDefault()
?.Invoke();
}
public sealed class Case
{
private readonly Func<bool> _condition;
private readonly Action _action;
public Func<bool> Condition { get { return _condition; } }
public Action Action { get { return _action; } }
public Case(Func<bool> condition, Action action)
{
_condition = condition;
_action = action;
}
}
}
Then the code looks like this:
int state1 = Animator.StringToHash("State1");
int state2 = Animator.StringToHash("State2");
int hash = _myAnimator.GetCurrentAnimatorStateInfo(0).shortNameHash;
var @switch = new Switch()
{
{ () => hash == state1, () => { /* Do stuff */} },
{ () => hash == state2, () => { /* Do other stuff */} },
};
@switch.Execute();
And if you write it like this it almost looks like a normal switch
statement:
var @switch = new Switch()
{
{
() => hash == state1,
() =>
{
/* Do stuff */
}
},
{
() => hash == state2,
() =>
{
/* Do other stuff */
}
},
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With