I am looking for an alternative to a Switch Statement....
I have a class which monitors the serial port for incoming data. Each
byte received represents a different action to perform, for example,
if byte '12' is received, it will instigate a 'bleep' sound. I
utilise around 100 different 'byte' codes, each performing a different
task.
In order to determine what action needs to be taken with the received
'byte' I process it through a switch statement containing 100 or so
different conditions. This to me does not seem like the best way of
doing it since if byte '99' is received it would have to cascade 98
other switch conditions before it gets to '99'. This to me seems
quite inefficient. Is there a better way to do it (other than to
break down the switch statement into nested switch statements)?
A switch creates a state machine, so efficiency is not the problem here.
With older languages, this was not always the case, and altering the
order of a switch type of branch would affect performance. This is NOT
the case in .NET.
What this means? If the switch is static (meaning it does not change,
not that it is shared across all instances of a class, as in the C#
static keyword), and perf is you only concern, leave it alone.
But, there is still a reason to can the switch, and it is maintenance.
By the time you have this many switches, you have a potential
maintainence nightmare. If you have to add items, it gets worse, as it
becomes harder to maintain.
By the time you have 100 items, it is generally time to refactor to a
metadata store. In a customer driven system (which yours is not), you
can actually do a lookup against the persistant store per request. If
you need a bit more perf in this scenario, you add caching so you remove
the overhead of retrieval. The negative of caching here is you have to
wait for a new item or manually refresh the cache.
With automated systems, however, looking up from a persistent data
store, or sometimes even cache, is not a wise option. In these cases,
you spin a "lookup table" into memory when the app starts. As an aside,
you can combine cache and the lookup table if it has to be aware of
changes to the metadata in real time.
Aside aside, the objects you use for lookup are lists, hashtables,
dictionaries and the like. use a generic implementation, when possible,
as you remove the overhead of boxing and unboxing for non-reference
types. Yes, I am speaking a lot of geek here.
In simple terms, you can do something like this (warning, sample only:
apply pattern, not specific code):
public class SerialInstructionDictionary : Dictionary<byte, string>
{
public void Load()
{
'Pull from persistent metadata store and assign to
'key/value pairs
}
}
You can then lookup like this (more pseudocode):
'pull first byte here
Byte byt = PullByteFromSerialString(serialString);
'get instruction
string instruction = dict[byt];
This assumes a string. There are more proper patterns (perhaps
strategy?) that you can employ if you want to load actual processes from
this lookup.
Let's summarize the points made. If you are merely worried about
performance, don't be. If, instead, you are also worried about
maintenance or simplifying you code (SOLID principles), then consider
some other lookup mechanism.
Glad you dropped in, I have another topic for a blog entry. ;-)
--
Gregory A. Beamer
MVP; MCP: +I, SE, SD, DBA
Twitter: @gbworld
Blog:
http://gregorybeamer.spaces.live.com
*******************************************
| Think outside the box! |
*******************************************