introduction
a switch-block becomes complex very easily. all code is placed in one method and parts of it are used multiple times. in a lot of cases, a switch-block is based on an <code>enumcode>. next to that, it's not possible to use a fall-through in c#. the only way to go from case to case is the use of the <code>gotocode> statement, which isn't a good idea when reducing complexity. although i've written the examples in c#, it wouldn't be hard to apply the principles to other languages.
a solution
a nice solution to get rid of large switch constructions is the use of a <code>dictionary<enum,delegate>code>. this way every element of the <code>enum code>can be attached to a method. it is possible to call the right method for every <code>enum code>possible. because every <code>enum code>has its own method, it's very easy to use this construction in a testdriven environment. another nice thing is that it's no problem to call one method from another. let me explain a little further with an example and some pseudo code. imagine a program that prepares food. this part contains the recipes.
let us start with the following <code>enumcode>:
enum food{
apple,
applepie,
applejuice,
pizza
}
it's not hard to imagine that all of the foods need a specific preparation, but that some actions need to be done for different foods, like peeling an apple or baking in the oven.
to add the preparations to the <code>dictionary<enum, delegate>code>, we first need to define a <code>delegate code>method:
delegate bool preperation();
now we need to define the actual preparation methods for every item of the <code>enumcode>, making sure they're declared the same way as the <code>delegatecode>, thus the same parameters and return value. the method returns a boolean when preparation is successful.
in this example, the methods may look something like this:
bool peelapple()
{
return true;
}
bool bakepie()
{
preheatoven(180.0);
peelapple();
createpie();
while(!donebaking())
bake();
return true;
}
bool makeapplejuice()
{
peelapple();
juicify();
return true;
}
bool bakepizza()
{
preheatoven(160.0);
createpizza();
while(!donebaking())
bake();
return true;
}
notice that <code>bakepie()code> and <code>makeapplejuice()code> both call the method <code>peelapple()code>. this is not possible in a <code>switch code>– case constructor, unless you call the methods from each case.
now all that's left is to create and initialize the <code>dictionarycode>.
dictionary foodpreperation;
..
foodpreperation = new dictionary<food, preperation>();
foodpreperation.add(food.apple, new preperation(peelapple));
foodpreperation.add(food.applepie, new preperation(bakepie));
foodpreperation.add(food.applejuice, new preperation(makeapplejuice));
foodpreperation.add(food.applepizza, new preperation(bakepizza));
calling the methods is done by:
food foodofchoice = food.applepie;
foodpreperation[foodofchoice]();
in the last code snippet, the method that goes with <code>food.applepiecode> is executed.
history
- 07 oct 2008 - initial upload